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 21 namespace clang { 22 inline StringRef getLambdaStaticInvokerName() { 23 return "__invoke"; 24 } 25 // This function returns true if M is a specialization, a template, 26 // or a non-generic lambda call operator. 27 inline bool isLambdaCallOperator(const CXXMethodDecl *MD) { 28 const CXXRecordDecl *LambdaClass = MD->getParent(); 29 if (!LambdaClass || !LambdaClass->isLambda()) return false; 30 return MD->getOverloadedOperator() == OO_Call; 31 } 32 33 inline bool isLambdaCallOperator(const DeclContext *DC) { 34 if (!DC || !isa<CXXMethodDecl>(DC)) return false; 35 return isLambdaCallOperator(cast<CXXMethodDecl>(DC)); 36 } 37 38 inline bool isLambdaCallWithExplicitObjectParameter(const DeclContext *DC) { 39 return isLambdaCallOperator(DC) && 40 cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction(); 41 } 42 43 inline bool isLambdaCallWithImplicitObjectParameter(const DeclContext *DC) { 44 return isLambdaCallOperator(DC) && 45 // FIXME: Checking for a null type is not great 46 // but lambdas with invalid captures or whose closure parameter list 47 // have not fully been parsed may have a call operator whose type is 48 // null. 49 !cast<CXXMethodDecl>(DC)->getType().isNull() && 50 !cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction(); 51 } 52 53 inline bool isGenericLambdaCallOperatorSpecialization(const CXXMethodDecl *MD) { 54 if (!MD) return false; 55 const CXXRecordDecl *LambdaClass = MD->getParent(); 56 if (LambdaClass && LambdaClass->isGenericLambda()) 57 return isLambdaCallOperator(MD) && 58 MD->isFunctionTemplateSpecialization(); 59 return false; 60 } 61 62 inline bool isLambdaConversionOperator(CXXConversionDecl *C) { 63 return C ? C->getParent()->isLambda() : false; 64 } 65 66 inline bool isLambdaConversionOperator(Decl *D) { 67 if (!D) return false; 68 if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D)) 69 return isLambdaConversionOperator(Conv); 70 if (FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(D)) 71 if (CXXConversionDecl *Conv = 72 dyn_cast_or_null<CXXConversionDecl>(F->getTemplatedDecl())) 73 return isLambdaConversionOperator(Conv); 74 return false; 75 } 76 77 inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) { 78 return isGenericLambdaCallOperatorSpecialization( 79 dyn_cast<CXXMethodDecl>(DC)); 80 } 81 82 inline bool isGenericLambdaCallOperatorOrStaticInvokerSpecialization( 83 const DeclContext *DC) { 84 const auto *MD = dyn_cast<CXXMethodDecl>(DC); 85 if (!MD) return false; 86 const CXXRecordDecl *LambdaClass = MD->getParent(); 87 if (LambdaClass && LambdaClass->isGenericLambda()) 88 return (isLambdaCallOperator(MD) || MD->isLambdaStaticInvoker()) && 89 MD->isFunctionTemplateSpecialization(); 90 return false; 91 } 92 93 // This returns the parent DeclContext ensuring that the correct 94 // parent DeclContext is returned for Lambdas 95 inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) { 96 if (isLambdaCallOperator(DC)) 97 return DC->getParent()->getParent(); 98 else 99 return DC->getParent(); 100 } 101 102 } // clang 103 104 #endif 105