clang 24.0.0git
AnyCall.h
Go to the documentation of this file.
1//=== AnyCall.h - Abstraction over different callables --------*- 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// A utility class for performing generic operations over different callables.
10//
11//===----------------------------------------------------------------------===//
12//
13#ifndef LLVM_CLANG_ANALYSIS_ANYCALL_H
14#define LLVM_CLANG_ANALYSIS_ANYCALL_H
15
16#include "clang/AST/Decl.h"
17#include "clang/AST/ExprCXX.h"
18#include "clang/AST/ExprObjC.h"
19#include <optional>
20
21namespace clang {
22
23/// An instance of this class corresponds to a call.
24/// It might be a syntactically-concrete call, done as a part of evaluating an
25/// expression, or it may be an abstract callee with no associated expression.
26class AnyCall {
27public:
28 enum Kind {
29 /// A function, function pointer, or a C++ method call
31
32 /// A call to an Objective-C method
34
35 /// A call to an Objective-C block
37
38 /// An implicit C++ destructor call (called implicitly
39 /// or by operator 'delete')
41
42 /// An implicit or explicit C++ constructor call
44
45 /// A C++ inherited constructor produced by a "using T::T" directive
47
48 /// A C++ allocation function call (operator `new`), via C++ new-expression
50
51 /// A C++ deallocation function call (operator `delete`), via C++
52 /// delete-expression
54 };
55
56private:
57 /// Either expression or declaration (but not both at the same time)
58 /// can be null.
59
60 /// Call expression, is null when is not known (then declaration is non-null),
61 /// or for implicit destructor calls (when no expression exists.)
62 const Expr *E = nullptr;
63
64 /// Corresponds to a statically known declaration of the called function,
65 /// or null if it is not known (e.g. for a function pointer).
66 const Decl *D = nullptr;
67 Kind K;
68
69public:
70 AnyCall(const CallExpr *CE) : E(CE) {
71 D = CE->getCalleeDecl();
72 K = (CE->getCallee()->getType()->getAs<BlockPointerType>()) ? Block
73 : Function;
74 if (D && ((K == Function && !isa<FunctionDecl>(D)) ||
75 (K == Block && !isa<BlockDecl>(D))))
76 D = nullptr;
77 }
78
80 : E(ME), D(ME->getMethodDecl()), K(ObjCMethod) {}
81
83 : E(NE), D(NE->getOperatorNew()), K(Allocator) {}
84
86 : E(NE), D(NE->getOperatorDelete()), K(Deallocator) {}
87
89 : E(NE), D(NE->getConstructor()), K(Constructor) {}
90
92 : E(CIE), D(CIE->getConstructor()), K(InheritedConstructor) {}
93
94 AnyCall(const CXXDestructorDecl *D) : E(nullptr), D(D), K(Destructor) {}
95
96 AnyCall(const CXXConstructorDecl *D) : E(nullptr), D(D), K(Constructor) {}
97
98 AnyCall(const ObjCMethodDecl *D) : E(nullptr), D(D), K(ObjCMethod) {}
99
100 AnyCall(const FunctionDecl *D) : E(nullptr), D(D) {
102 K = Constructor;
103 } else if (isa <CXXDestructorDecl>(D)) {
104 K = Destructor;
105 } else {
106 K = Function;
107 }
108
109 }
110
111 /// If @c E is a generic call (to ObjC method /function/block/etc),
112 /// return a constructed @c AnyCall object. Return std::nullopt otherwise.
113 static std::optional<AnyCall> forExpr(const Expr *E) {
114 if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
115 return AnyCall(ME);
116 } else if (const auto *CE = dyn_cast<CallExpr>(E)) {
117 return AnyCall(CE);
118 } else if (const auto *CXNE = dyn_cast<CXXNewExpr>(E)) {
119 return AnyCall(CXNE);
120 } else if (const auto *CXDE = dyn_cast<CXXDeleteExpr>(E)) {
121 return AnyCall(CXDE);
122 } else if (const auto *CXCE = dyn_cast<CXXConstructExpr>(E)) {
123 return AnyCall(CXCE);
124 } else if (const auto *CXCIE = dyn_cast<CXXInheritedCtorInitExpr>(E)) {
125 return AnyCall(CXCIE);
126 } else {
127 return std::nullopt;
128 }
129 }
130
131 /// If @c D is a callable (Objective-C method or a function), return
132 /// a constructed @c AnyCall object. Return std::nullopt otherwise.
133 // FIXME: block support.
134 static std::optional<AnyCall> forDecl(const Decl *D) {
135 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
136 return AnyCall(FD);
137 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
138 return AnyCall(MD);
139 }
140 return std::nullopt;
141 }
142
143 /// \returns formal parameters for direct calls (including virtual calls)
145 if (!D)
146 return {};
147
148 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
149 return FD->parameters();
150 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
151 return MD->parameters();
152 } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
153 return BD->parameters();
154 } else {
155 return {};
156 }
157 }
158
160 param_const_iterator param_begin() const { return parameters().begin(); }
161 param_const_iterator param_end() const { return parameters().end(); }
162 size_t param_size() const { return parameters().size(); }
163 bool param_empty() const { return parameters().empty(); }
164
165 /// \returns actual arguments for expression-backed calls, or an empty range
166 /// for declaration-backed calls and call kinds with implicit or synthesized
167 /// argument lists, such as allocators and destructors.
169 if (!E)
170 return {};
171
172 switch (K) {
173 case Function:
174 case Block: {
175 const auto *CE = cast<CallExpr>(E);
176 return {CE->getArgs(), CE->getNumArgs()};
177 }
178 case ObjCMethod: {
179 const auto *ME = cast<ObjCMessageExpr>(E);
180 return {ME->getArgs(), ME->getNumArgs()};
181 }
182 case Constructor: {
183 const auto *CE = cast<CXXConstructExpr>(E);
184 return {CE->getArgs(), CE->getNumArgs()};
185 }
186 case Destructor:
188 case Allocator:
189 case Deallocator:
190 return {};
191 }
192 llvm_unreachable("Unknown AnyCall::Kind");
193 }
194
196 arg_const_iterator arg_begin() const { return arguments().begin(); }
197 arg_const_iterator arg_end() const { return arguments().end(); }
198 size_t arg_size() const { return arguments().size(); }
199 bool arg_empty() const { return arguments().empty(); }
200 const Expr *getArg(unsigned I) const { return arguments()[I]; }
201
203 switch (K) {
204 case Function:
205 if (E)
206 return cast<CallExpr>(E)->getCallReturnType(Ctx);
207 return cast<FunctionDecl>(D)->getReturnType();
208 case ObjCMethod:
209 if (E)
210 return cast<ObjCMessageExpr>(E)->getCallReturnType(Ctx);
211 return cast<ObjCMethodDecl>(D)->getReturnType();
212 case Block:
213 // FIXME: BlockDecl does not know its return type,
214 // hence the asymmetry with the function and method cases above.
215 return cast<CallExpr>(E)->getCallReturnType(Ctx);
216 case Destructor:
217 case Constructor:
219 case Allocator:
220 case Deallocator:
221 return cast<FunctionDecl>(D)->getReturnType();
222 }
223 llvm_unreachable("Unknown AnyCall::Kind");
224 }
225
226 /// \returns Function identifier if it is a named declaration,
227 /// @c nullptr otherwise.
229 if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
230 return ND->getIdentifier();
231 return nullptr;
232 }
233
234 const Decl *getDecl() const {
235 return D;
236 }
237
238 const Expr *getExpr() const {
239 return E;
240 }
241
242 Kind getKind() const {
243 return K;
244 }
245
246 void dump() const {
247 if (E)
248 E->dump();
249 if (D)
250 D->dump();
251 }
252};
253
254}
255
256#endif // LLVM_CLANG_ANALYSIS_ANYCALL_H
Defines the clang::Expr interface and subclasses for C++ expressions.
TokenType getType() const
Returns the token's type, e.g.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
bool arg_empty() const
Definition AnyCall.h:199
size_t param_size() const
Definition AnyCall.h:162
AnyCall(const CXXConstructExpr *NE)
Definition AnyCall.h:88
ArrayRef< ParmVarDecl * >::const_iterator param_const_iterator
Definition AnyCall.h:159
param_const_iterator param_end() const
Definition AnyCall.h:161
Kind getKind() const
Definition AnyCall.h:242
ArrayRef< const Expr * > arguments() const
Definition AnyCall.h:168
AnyCall(const CallExpr *CE)
Definition AnyCall.h:70
const Decl * getDecl() const
Definition AnyCall.h:234
AnyCall(const CXXDestructorDecl *D)
Definition AnyCall.h:94
const IdentifierInfo * getIdentifier() const
Definition AnyCall.h:228
arg_const_iterator arg_begin() const
Definition AnyCall.h:196
param_const_iterator param_begin() const
Definition AnyCall.h:160
void dump() const
Definition AnyCall.h:246
AnyCall(const CXXNewExpr *NE)
Definition AnyCall.h:82
size_t arg_size() const
Definition AnyCall.h:198
static std::optional< AnyCall > forDecl(const Decl *D)
If D is a callable (Objective-C method or a function), return a constructed AnyCall object.
Definition AnyCall.h:134
arg_const_iterator arg_end() const
Definition AnyCall.h:197
AnyCall(const ObjCMessageExpr *ME)
Definition AnyCall.h:79
static std::optional< AnyCall > forExpr(const Expr *E)
If E is a generic call (to ObjC method /function/block/etc), return a constructed AnyCall object.
Definition AnyCall.h:113
AnyCall(const CXXConstructorDecl *D)
Definition AnyCall.h:96
AnyCall(const CXXInheritedCtorInitExpr *CIE)
Definition AnyCall.h:91
ArrayRef< ParmVarDecl * > parameters() const
Definition AnyCall.h:144
@ Destructor
An implicit C++ destructor call (called implicitly or by operator 'delete')
Definition AnyCall.h:40
@ ObjCMethod
A call to an Objective-C method.
Definition AnyCall.h:33
@ Deallocator
A C++ deallocation function call (operator delete), via C++ delete-expression.
Definition AnyCall.h:53
@ Function
A function, function pointer, or a C++ method call.
Definition AnyCall.h:30
@ Allocator
A C++ allocation function call (operator new), via C++ new-expression.
Definition AnyCall.h:49
@ Constructor
An implicit or explicit C++ constructor call.
Definition AnyCall.h:43
@ InheritedConstructor
A C++ inherited constructor produced by a "using T::T" directive.
Definition AnyCall.h:46
@ Block
A call to an Objective-C block.
Definition AnyCall.h:36
AnyCall(const ObjCMethodDecl *D)
Definition AnyCall.h:98
QualType getReturnType(ASTContext &Ctx) const
Definition AnyCall.h:202
const Expr * getArg(unsigned I) const
Definition AnyCall.h:200
const Expr * getExpr() const
Definition AnyCall.h:238
AnyCall(const CXXDeleteExpr *NE)
Definition AnyCall.h:85
AnyCall(const FunctionDecl *D)
Definition AnyCall.h:100
bool param_empty() const
Definition AnyCall.h:163
ArrayRef< const Expr * >::const_iterator arg_const_iterator
Definition AnyCall.h:195
Represents a call to a C++ constructor.
Definition ExprCXX.h:1551
Represents a C++ constructor within a class.
Definition DeclCXX.h:2633
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2629
Represents a C++ destructor within a class.
Definition DeclCXX.h:2898
Represents a call to an inherited base class constructor from an inheriting constructor.
Definition ExprCXX.h:1754
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2358
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2949
Expr * getCallee()
Definition Expr.h:3096
Decl * getCalleeDecl()
Definition Expr.h:3126
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
This represents one expression.
Definition Expr.h:112
Represents a function declaration or definition.
Definition Decl.h:2029
One of these records is kept for each identifier that is lexed.
An expression that sends a message to the given Objective-C object or class.
Definition ExprObjC.h:973
ObjCMethodDecl - Represents an instance or class method declaration.
Definition DeclObjC.h:140
A (possibly-)qualified type.
Definition TypeBase.h:938
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
U cast(CodeGen::Address addr)
Definition Address.h:327