]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Analysis/AnyCall.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Analysis / AnyCall.h
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_ANY_CALL_H
14 #define LLVM_CLANG_ANALYSIS_ANY_CALL_H
15
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/ExprCXX.h"
18 #include "clang/AST/ExprObjC.h"
19
20 namespace clang {
21
22 /// An instance of this class corresponds to a call.
23 /// It might be a syntactically-concrete call, done as a part of evaluating an
24 /// expression, or it may be an abstract callee with no associated expression.
25 class AnyCall {
26 public:
27   enum Kind {
28     /// A function, function pointer, or a C++ method call
29     Function,
30
31     /// A call to an Objective-C method
32     ObjCMethod,
33
34     /// A call to an Objective-C block
35     Block,
36
37     /// An implicit C++ destructor call (called implicitly
38     /// or by operator 'delete')
39     Destructor,
40
41     /// An implicit or explicit C++ constructor call
42     Constructor,
43
44     /// A C++ allocation function call (operator `new`), via C++ new-expression
45     Allocator,
46
47     /// A C++ deallocation function call (operator `delete`), via C++
48     /// delete-expression
49     Deallocator
50   };
51
52 private:
53   /// Either expression or declaration (but not both at the same time)
54   /// can be null.
55
56   /// Call expression, is null when is not known (then declaration is non-null),
57   /// or for implicit destructor calls (when no expression exists.)
58   const Expr *E = nullptr;
59
60   /// Corresponds to a statically known declaration of the called function,
61   /// or null if it is not known (e.g. for a function pointer).
62   const Decl *D = nullptr;
63   Kind K;
64
65 public:
66   AnyCall(const CallExpr *CE) : E(CE) {
67     D = CE->getCalleeDecl();
68     K = (CE->getCallee()->getType()->getAs<BlockPointerType>()) ? Block
69                                                                 : Function;
70     if (D && ((K == Function && !isa<FunctionDecl>(D)) ||
71               (K == Block && !isa<BlockDecl>(D))))
72       D = nullptr;
73   }
74
75   AnyCall(const ObjCMessageExpr *ME)
76       : E(ME), D(ME->getMethodDecl()), K(ObjCMethod) {}
77
78   AnyCall(const CXXNewExpr *NE)
79       : E(NE), D(NE->getOperatorNew()), K(Allocator) {}
80
81   AnyCall(const CXXDeleteExpr *NE)
82       : E(NE), D(NE->getOperatorDelete()), K(Deallocator) {}
83
84   AnyCall(const CXXConstructExpr *NE)
85       : E(NE), D(NE->getConstructor()), K(Constructor) {}
86
87   AnyCall(const CXXDestructorDecl *D) : E(nullptr), D(D), K(Destructor) {}
88
89   AnyCall(const CXXConstructorDecl *D) : E(nullptr), D(D), K(Constructor) {}
90
91   AnyCall(const ObjCMethodDecl *D) : E(nullptr), D(D), K(ObjCMethod) {}
92
93   AnyCall(const FunctionDecl *D) : E(nullptr), D(D) {
94     if (isa<CXXConstructorDecl>(D)) {
95       K = Constructor;
96     } else if (isa <CXXDestructorDecl>(D)) {
97       K = Destructor;
98     } else {
99       K = Function;
100     }
101
102   }
103
104   /// If {@code E} is a generic call (to ObjC method /function/block/etc),
105   /// return a constructed {@code AnyCall} object. Return None otherwise.
106   static Optional<AnyCall> forExpr(const Expr *E) {
107     if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
108       return AnyCall(ME);
109     } else if (const auto *CE = dyn_cast<CallExpr>(E)) {
110       return AnyCall(CE);
111     } else if (const auto *CXNE = dyn_cast<CXXNewExpr>(E)) {
112       return AnyCall(CXNE);
113     } else if (const auto *CXDE = dyn_cast<CXXDeleteExpr>(E)) {
114       return AnyCall(CXDE);
115     } else if (const auto *CXCE = dyn_cast<CXXConstructExpr>(E)) {
116       return AnyCall(CXCE);
117     } else {
118       return None;
119     }
120   }
121
122   /// If {@code D} is a callable (Objective-C method or a function), return
123   /// a constructed {@code AnyCall} object. Return None otherwise.
124   // FIXME: block support.
125   static Optional<AnyCall> forDecl(const Decl *D) {
126     if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
127       return AnyCall(FD);
128     } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
129       return AnyCall(MD);
130     }
131     return None;
132   }
133
134   /// \returns formal parameters for direct calls (including virtual calls)
135   ArrayRef<ParmVarDecl *> parameters() const {
136     if (!D)
137       return None;
138
139     if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
140       return FD->parameters();
141     } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
142       return MD->parameters();
143     } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
144       return BD->parameters();
145     } else {
146       return None;
147     }
148   }
149
150   using param_const_iterator = ArrayRef<ParmVarDecl *>::const_iterator;
151   param_const_iterator param_begin() const { return parameters().begin(); }
152   param_const_iterator param_end() const { return parameters().end(); }
153   size_t param_size() const { return parameters().size(); }
154   bool param_empty() const { return parameters().empty(); }
155
156   QualType getReturnType(ASTContext &Ctx) const {
157     switch (K) {
158     case Function:
159       if (E)
160         return cast<CallExpr>(E)->getCallReturnType(Ctx);
161       return cast<FunctionDecl>(D)->getReturnType();
162     case ObjCMethod:
163       if (E)
164         return cast<ObjCMessageExpr>(E)->getCallReturnType(Ctx);
165       return cast<ObjCMethodDecl>(D)->getReturnType();
166     case Block:
167       // FIXME: BlockDecl does not know its return type,
168       // hence the asymmetry with the function and method cases above.
169       return cast<CallExpr>(E)->getCallReturnType(Ctx);
170     case Destructor:
171     case Constructor:
172     case Allocator:
173     case Deallocator:
174       return cast<FunctionDecl>(D)->getReturnType();
175     }
176     llvm_unreachable("Unknown AnyCall::Kind");
177   }
178
179   /// \returns Function identifier if it is a named declaration,
180   /// {@code nullptr} otherwise.
181   const IdentifierInfo *getIdentifier() const {
182     if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
183       return ND->getIdentifier();
184     return nullptr;
185   }
186
187   const Decl *getDecl() const {
188     return D;
189   }
190
191   const Expr *getExpr() const {
192     return E;
193   }
194
195   Kind getKind() const {
196     return K;
197   }
198
199   void dump() const {
200     if (E)
201       E->dump();
202     if (D)
203       D->dump();
204   }
205 };
206
207 }
208
209 #endif // LLVM_CLANG_ANALYSIS_ANY_CALL_H