1 //===--- ASTLambda.h - Lambda Helper Functions --------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file provides some common utility functions for processing 11 /// Lambda related AST Constructs. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_AST_ASTLAMBDA_H 16 #define LLVM_CLANG_AST_ASTLAMBDA_H 17 18 #include "clang/AST/DeclCXX.h" 19 #include "clang/AST/DeclTemplate.h" 20 #include "llvm/Support/Casting.h" 21 22 namespace clang { 23 inline StringRef getLambdaStaticInvokerName() { 24 return "__invoke"; 25 } 26 // This function returns true if M is a specialization, a template, 27 // or a non-generic lambda call operator. 28 inline bool isLambdaCallOperator(const CXXMethodDecl *MD) { 29 const CXXRecordDecl *LambdaClass = MD->getParent(); 30 if (!LambdaClass || !LambdaClass->isLambda()) return false; 31 return MD->getOverloadedOperator() == OO_Call; 32 } 33 34 inline bool isLambdaCallOperator(const DeclContext *DC) { 35 if (!DC || !isa<CXXMethodDecl>(DC)) return false; 36 return isLambdaCallOperator(cast<CXXMethodDecl>(DC)); 37 } 38 39 inline bool isLambdaMethod(const DeclContext *DC) { 40 if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(DC)) 41 return MD->getParent()->isLambda(); 42 return false; 43 } 44 45 inline bool isLambdaCallWithExplicitObjectParameter(const DeclContext *DC) { 46 return isLambdaCallOperator(DC) && 47 cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction(); 48 } 49 50 inline bool isLambdaCallWithImplicitObjectParameter(const DeclContext *DC) { 51 return isLambdaCallOperator(DC) && 52 // FIXME: Checking for a null type is not great 53 // but lambdas with invalid captures or whose closure parameter list 54 // have not fully been parsed may have a call operator whose type is 55 // null. 56 !cast<CXXMethodDecl>(DC)->getType().isNull() && 57 !cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction(); 58 } 59 60 inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl *MD) { 61 if (!MD) return false; 62 const CXXRecordDecl *LambdaClass = MD->getParent(); 63 if (LambdaClass && LambdaClass->isGenericLambda()) 64 return isLambdaCallOperator(MD) && 65 MD->isFunctionTemplateSpecialization(); 66 return false; 67 } 68 69 inline bool isLambdaConversionOperator(CXXConversionDecl *C) { 70 return C ? C->getParent()->isLambda() : false; 71 } 72 73 inline bool isLambdaConversionOperator(Decl *D) { 74 if (!D) return false; 75 if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D)) 76 return isLambdaConversionOperator(Conv); 77 if (FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(D)) 78 if (CXXConversionDecl *Conv = 79 dyn_cast_or_null<CXXConversionDecl>(F->getTemplatedDecl())) 80 return isLambdaConversionOperator(Conv); 81 return false; 82 } 83 84 inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) { 85 return isGenericLambdaCallOperatorSpecialization( 86 dyn_cast<CXXMethodDecl>(DC)); 87 } 88 89 inline bool isGenericLambdaCallOperatorOrStaticInvokerSpecialization( 90 const DeclContext *DC) { 91 const auto *MD = dyn_cast<CXXMethodDecl>(DC); 92 if (!MD) return false; 93 const CXXRecordDecl *LambdaClass = MD->getParent(); 94 if (LambdaClass && LambdaClass->isGenericLambda()) 95 return (isLambdaCallOperator(MD) || MD->isLambdaStaticInvoker()) && 96 MD->isFunctionTemplateSpecialization(); 97 return false; 98 } 99 100 // This returns the parent DeclContext ensuring that the correct 101 // parent DeclContext is returned for Lambdas 102 inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) { 103 if (isLambdaCallOperator(DC)) 104 return DC->getParent()->getParent(); 105 else 106 return DC->getParent(); 107 } 108 109 } // clang 110 111 #endif 112