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 "llvm/ADT/SmallVector.h"
20#include <optional>
21
22namespace clang {
23
24/// An instance of this class corresponds to a call.
25/// It might be a syntactically-concrete call, done as a part of evaluating an
26/// expression, or it may be an abstract callee with no associated expression.
27class AnyCall {
28public:
29 enum Kind {
30 /// A function, function pointer, or a C++ method call
32
33 /// A call to an Objective-C method
35
36 /// A call to an Objective-C block
38
39 /// An implicit C++ destructor call (called implicitly
40 /// or by operator 'delete')
42
43 /// An implicit or explicit C++ constructor call
45
46 /// A C++ inherited constructor produced by a "using T::T" directive
48
49 /// A C++ allocation function call (operator `new`), via C++ new-expression
51
52 /// A C++ deallocation function call (operator `delete`), via C++
53 /// delete-expression
55 };
56
57private:
58 /// Either expression or declaration (but not both at the same time)
59 /// can be null.
60
61 /// Call expression, is null when is not known (then declaration is non-null),
62 /// or for implicit destructor calls (when no expression exists.)
63 const Expr *E = nullptr;
64
65 /// Corresponds to a statically known declaration of the called function,
66 /// or null if it is not known (e.g. for a function pointer).
67 const Decl *D = nullptr;
68 Kind K;
69
70public:
71 AnyCall(const CallExpr *CE) : E(CE) {
72 D = CE->getCalleeDecl();
73 K = (CE->getCallee()->getType()->getAs<BlockPointerType>()) ? Block
74 : Function;
75 if (D && ((K == Function && !isa<FunctionDecl>(D)) ||
76 (K == Block && !isa<BlockDecl>(D))))
77 D = nullptr;
78 }
79
81 : E(ME), D(ME->getMethodDecl()), K(ObjCMethod) {}
82
84 : E(NE), D(NE->getOperatorNew()), K(Allocator) {}
85
87 : E(NE), D(NE->getOperatorDelete()), K(Deallocator) {}
88
90 : E(NE), D(NE->getConstructor()), K(Constructor) {}
91
93 : E(CIE), D(CIE->getConstructor()), K(InheritedConstructor) {}
94
95 AnyCall(const CXXDestructorDecl *D) : E(nullptr), D(D), K(Destructor) {}
96
97 AnyCall(const CXXConstructorDecl *D) : E(nullptr), D(D), K(Constructor) {}
98
99 AnyCall(const ObjCMethodDecl *D) : E(nullptr), D(D), K(ObjCMethod) {}
100
101 AnyCall(const FunctionDecl *D) : E(nullptr), D(D) {
103 K = Constructor;
104 } else if (isa <CXXDestructorDecl>(D)) {
105 K = Destructor;
106 } else {
107 K = Function;
108 }
109
110 }
111
112 /// If @c E is a generic call (to ObjC method /function/block/etc),
113 /// return a constructed @c AnyCall object. Return std::nullopt otherwise.
114 static std::optional<AnyCall> forExpr(const Expr *E) {
115 if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
116 return AnyCall(ME);
117 } else if (const auto *CE = dyn_cast<CallExpr>(E)) {
118 return AnyCall(CE);
119 } else if (const auto *CXNE = dyn_cast<CXXNewExpr>(E)) {
120 return AnyCall(CXNE);
121 } else if (const auto *CXDE = dyn_cast<CXXDeleteExpr>(E)) {
122 return AnyCall(CXDE);
123 } else if (const auto *CXCE = dyn_cast<CXXConstructExpr>(E)) {
124 return AnyCall(CXCE);
125 } else if (const auto *CXCIE = dyn_cast<CXXInheritedCtorInitExpr>(E)) {
126 return AnyCall(CXCIE);
127 } else {
128 return std::nullopt;
129 }
130 }
131
132 /// If @c D is a callable (Objective-C method or a function), return
133 /// a constructed @c AnyCall object. Return std::nullopt otherwise.
134 // FIXME: block support.
135 static std::optional<AnyCall> forDecl(const Decl *D) {
136 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
137 return AnyCall(FD);
138 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
139 return AnyCall(MD);
140 }
141 return std::nullopt;
142 }
143
144 /// \returns formal parameters for direct calls (including virtual calls)
146 if (!D)
147 return {};
148
149 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
150 return FD->parameters();
151 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
152 return MD->parameters();
153 } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
154 return BD->parameters();
155 } else {
156 return {};
157 }
158 }
159
161 param_const_iterator param_begin() const { return parameters().begin(); }
162 param_const_iterator param_end() const { return parameters().end(); }
163 size_t param_size() const { return parameters().size(); }
164 bool param_empty() const { return parameters().empty(); }
165
166 /// \returns actual arguments for expression-backed calls, or an empty list
167 /// for declaration-backed calls and call kinds with implicit or synthesized
168 /// argument lists, such as allocators and destructors. For instance member
169 /// calls, the implicit object argument is included as argument 0.
171 if (!E)
172 return {};
173
174 switch (K) {
175 case Function: {
177 const auto *CE = cast<CallExpr>(E);
178 if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(CE))
179 Args.push_back(MCE->getImplicitObjectArgument());
180 Args.append(CE->arg_begin(), CE->arg_end());
181
182 if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(CE))
183 // For `static operator()`, the first argument is the object argument,
184 // remove it from the argument list to avoid off-by-one errors.
185 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D);
186 FD && FD->isStatic() && OCE->getOperator() == OO_Call)
187 Args.erase(Args.begin());
188 return Args;
189 }
190 case Block: {
191 const auto *CE = cast<CallExpr>(E);
192 return {CE->arg_begin(), CE->arg_end()};
193 }
194 case ObjCMethod: {
195 const auto *ME = cast<ObjCMessageExpr>(E);
196 return {ME->arg_begin(), ME->arg_end()};
197 }
198 case Constructor: {
199 const auto *CE = cast<CXXConstructExpr>(E);
200 return {CE->arg_begin(), CE->arg_end()};
201 }
202 case Destructor:
204 case Allocator:
205 case Deallocator:
206 return {};
207 }
208 llvm_unreachable("Unknown AnyCall::Kind");
209 }
210
211 // These methods materialize the normalized argument list on each call, which
212 // can be expensive if used repeatedly. Prefer caching `arguments()` locally
213 // when accessing multiple arguments.
214 size_t arg_size() const { return arguments().size(); }
215 bool arg_empty() const { return arguments().empty(); }
216 const Expr *getArg(unsigned I) const { return arguments()[I]; }
217
219 switch (K) {
220 case Function:
221 if (E)
222 return cast<CallExpr>(E)->getCallReturnType(Ctx);
223 return cast<FunctionDecl>(D)->getReturnType();
224 case ObjCMethod:
225 if (E)
226 return cast<ObjCMessageExpr>(E)->getCallReturnType(Ctx);
227 return cast<ObjCMethodDecl>(D)->getReturnType();
228 case Block:
229 // FIXME: BlockDecl does not know its return type,
230 // hence the asymmetry with the function and method cases above.
231 return cast<CallExpr>(E)->getCallReturnType(Ctx);
232 case Destructor:
233 case Constructor:
235 case Allocator:
236 case Deallocator:
237 return cast<FunctionDecl>(D)->getReturnType();
238 }
239 llvm_unreachable("Unknown AnyCall::Kind");
240 }
241
242 /// \returns Function identifier if it is a named declaration,
243 /// @c nullptr otherwise.
245 if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
246 return ND->getIdentifier();
247 return nullptr;
248 }
249
250 const Decl *getDecl() const {
251 return D;
252 }
253
254 const Expr *getExpr() const {
255 return E;
256 }
257
258 Kind getKind() const {
259 return K;
260 }
261
262 void dump() const {
263 if (E)
264 E->dump();
265 if (D)
266 D->dump();
267 }
268};
269
270}
271
272#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:239
bool arg_empty() const
Definition AnyCall.h:215
size_t param_size() const
Definition AnyCall.h:163
AnyCall(const CXXConstructExpr *NE)
Definition AnyCall.h:89
ArrayRef< ParmVarDecl * >::const_iterator param_const_iterator
Definition AnyCall.h:160
param_const_iterator param_end() const
Definition AnyCall.h:162
Kind getKind() const
Definition AnyCall.h:258
AnyCall(const CallExpr *CE)
Definition AnyCall.h:71
const Decl * getDecl() const
Definition AnyCall.h:250
AnyCall(const CXXDestructorDecl *D)
Definition AnyCall.h:95
const IdentifierInfo * getIdentifier() const
Definition AnyCall.h:244
param_const_iterator param_begin() const
Definition AnyCall.h:161
void dump() const
Definition AnyCall.h:262
AnyCall(const CXXNewExpr *NE)
Definition AnyCall.h:83
size_t arg_size() const
Definition AnyCall.h:214
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:135
AnyCall(const ObjCMessageExpr *ME)
Definition AnyCall.h:80
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:114
AnyCall(const CXXConstructorDecl *D)
Definition AnyCall.h:97
AnyCall(const CXXInheritedCtorInitExpr *CIE)
Definition AnyCall.h:92
ArrayRef< ParmVarDecl * > parameters() const
Definition AnyCall.h:145
@ Destructor
An implicit C++ destructor call (called implicitly or by operator 'delete')
Definition AnyCall.h:41
@ ObjCMethod
A call to an Objective-C method.
Definition AnyCall.h:34
@ Deallocator
A C++ deallocation function call (operator delete), via C++ delete-expression.
Definition AnyCall.h:54
@ Function
A function, function pointer, or a C++ method call.
Definition AnyCall.h:31
@ Allocator
A C++ allocation function call (operator new), via C++ new-expression.
Definition AnyCall.h:50
@ Constructor
An implicit or explicit C++ constructor call.
Definition AnyCall.h:44
@ InheritedConstructor
A C++ inherited constructor produced by a "using T::T" directive.
Definition AnyCall.h:47
@ Block
A call to an Objective-C block.
Definition AnyCall.h:37
AnyCall(const ObjCMethodDecl *D)
Definition AnyCall.h:99
QualType getReturnType(ASTContext &Ctx) const
Definition AnyCall.h:218
const Expr * getArg(unsigned I) const
Definition AnyCall.h:216
llvm::SmallVector< const Expr *, 4 > arguments() const
Definition AnyCall.h:170
const Expr * getExpr() const
Definition AnyCall.h:254
AnyCall(const CXXDeleteExpr *NE)
Definition AnyCall.h:86
AnyCall(const FunctionDecl *D)
Definition AnyCall.h:101
bool param_empty() const
Definition AnyCall.h:164
Represents a call to a C++ constructor.
Definition ExprCXX.h:1552
Represents a C++ constructor within a class.
Definition DeclCXX.h:2641
Represents a delete expression for memory deallocation and destructor calls, e.g.
Definition ExprCXX.h:2630
Represents a C++ destructor within a class.
Definition DeclCXX.h:2906
Represents a call to an inherited base class constructor from an inheriting constructor.
Definition ExprCXX.h:1755
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
Definition ExprCXX.h:2359
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2987
Expr * getCallee()
Definition Expr.h:3134
Decl * getCalleeDecl()
Definition Expr.h:3164
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
This represents one expression.
Definition Expr.h:113
Represents a function declaration or definition.
Definition Decl.h:2059
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:972
ObjCMethodDecl - Represents an instance or class method declaration.
Definition DeclObjC.h:140
A (possibly-)qualified type.
Definition TypeBase.h:938
Top level wrappers for InstallAPI frontend operations.
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