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
22namespace clang {
23inline 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.
28inline 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
34inline bool isLambdaCallOperator(const DeclContext *DC) {
35 if (!DC || !isa<CXXMethodDecl>(Val: DC)) return false;
36 return isLambdaCallOperator(MD: cast<CXXMethodDecl>(Val: DC));
37}
38
39inline bool isLambdaMethod(const DeclContext *DC) {
40 if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(Val: DC))
41 return MD->getParent()->isLambda();
42 return false;
43}
44
45inline bool isLambdaCallWithExplicitObjectParameter(const DeclContext *DC) {
46 return isLambdaCallOperator(DC) &&
47 cast<CXXMethodDecl>(Val: DC)->isExplicitObjectMemberFunction();
48}
49
50inline 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>(Val: DC)->getType().isNull() &&
57 !cast<CXXMethodDecl>(Val: DC)->isExplicitObjectMemberFunction();
58}
59
60inline 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
69inline bool isLambdaConversionOperator(CXXConversionDecl *C) {
70 return C ? C->getParent()->isLambda() : false;
71}
72
73inline bool isLambdaConversionOperator(Decl *D) {
74 if (!D) return false;
75 if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(Val: D))
76 return isLambdaConversionOperator(C: Conv);
77 if (FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(Val: D))
78 if (CXXConversionDecl *Conv =
79 dyn_cast_or_null<CXXConversionDecl>(Val: F->getTemplatedDecl()))
80 return isLambdaConversionOperator(C: Conv);
81 return false;
82}
83
84inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) {
85 return isGenericLambdaCallOperatorSpecialization(
86 MD: dyn_cast<CXXMethodDecl>(Val: DC));
87}
88
89inline bool isGenericLambdaCallOperatorOrStaticInvokerSpecialization(
90 const DeclContext *DC) {
91 const auto *MD = dyn_cast<CXXMethodDecl>(Val: 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
102inline 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