File indexing completed on 2026-05-10 08:36:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_CLANG_ANALYSIS_ANYCALL_H
0014 #define LLVM_CLANG_ANALYSIS_ANYCALL_H
0015
0016 #include "clang/AST/Decl.h"
0017 #include "clang/AST/ExprCXX.h"
0018 #include "clang/AST/ExprObjC.h"
0019 #include <optional>
0020
0021 namespace clang {
0022
0023
0024
0025
0026 class AnyCall {
0027 public:
0028 enum Kind {
0029
0030 Function,
0031
0032
0033 ObjCMethod,
0034
0035
0036 Block,
0037
0038
0039
0040 Destructor,
0041
0042
0043 Constructor,
0044
0045
0046 InheritedConstructor,
0047
0048
0049 Allocator,
0050
0051
0052
0053 Deallocator
0054 };
0055
0056 private:
0057
0058
0059
0060
0061
0062 const Expr *E = nullptr;
0063
0064
0065
0066 const Decl *D = nullptr;
0067 Kind K;
0068
0069 public:
0070 AnyCall(const CallExpr *CE) : E(CE) {
0071 D = CE->getCalleeDecl();
0072 K = (CE->getCallee()->getType()->getAs<BlockPointerType>()) ? Block
0073 : Function;
0074 if (D && ((K == Function && !isa<FunctionDecl>(D)) ||
0075 (K == Block && !isa<BlockDecl>(D))))
0076 D = nullptr;
0077 }
0078
0079 AnyCall(const ObjCMessageExpr *ME)
0080 : E(ME), D(ME->getMethodDecl()), K(ObjCMethod) {}
0081
0082 AnyCall(const CXXNewExpr *NE)
0083 : E(NE), D(NE->getOperatorNew()), K(Allocator) {}
0084
0085 AnyCall(const CXXDeleteExpr *NE)
0086 : E(NE), D(NE->getOperatorDelete()), K(Deallocator) {}
0087
0088 AnyCall(const CXXConstructExpr *NE)
0089 : E(NE), D(NE->getConstructor()), K(Constructor) {}
0090
0091 AnyCall(const CXXInheritedCtorInitExpr *CIE)
0092 : E(CIE), D(CIE->getConstructor()), K(InheritedConstructor) {}
0093
0094 AnyCall(const CXXDestructorDecl *D) : E(nullptr), D(D), K(Destructor) {}
0095
0096 AnyCall(const CXXConstructorDecl *D) : E(nullptr), D(D), K(Constructor) {}
0097
0098 AnyCall(const ObjCMethodDecl *D) : E(nullptr), D(D), K(ObjCMethod) {}
0099
0100 AnyCall(const FunctionDecl *D) : E(nullptr), D(D) {
0101 if (isa<CXXConstructorDecl>(D)) {
0102 K = Constructor;
0103 } else if (isa <CXXDestructorDecl>(D)) {
0104 K = Destructor;
0105 } else {
0106 K = Function;
0107 }
0108
0109 }
0110
0111
0112
0113 static std::optional<AnyCall> forExpr(const Expr *E) {
0114 if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
0115 return AnyCall(ME);
0116 } else if (const auto *CE = dyn_cast<CallExpr>(E)) {
0117 return AnyCall(CE);
0118 } else if (const auto *CXNE = dyn_cast<CXXNewExpr>(E)) {
0119 return AnyCall(CXNE);
0120 } else if (const auto *CXDE = dyn_cast<CXXDeleteExpr>(E)) {
0121 return AnyCall(CXDE);
0122 } else if (const auto *CXCE = dyn_cast<CXXConstructExpr>(E)) {
0123 return AnyCall(CXCE);
0124 } else if (const auto *CXCIE = dyn_cast<CXXInheritedCtorInitExpr>(E)) {
0125 return AnyCall(CXCIE);
0126 } else {
0127 return std::nullopt;
0128 }
0129 }
0130
0131
0132
0133
0134 static std::optional<AnyCall> forDecl(const Decl *D) {
0135 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
0136 return AnyCall(FD);
0137 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
0138 return AnyCall(MD);
0139 }
0140 return std::nullopt;
0141 }
0142
0143
0144 ArrayRef<ParmVarDecl *> parameters() const {
0145 if (!D)
0146 return {};
0147
0148 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
0149 return FD->parameters();
0150 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
0151 return MD->parameters();
0152 } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
0153 return BD->parameters();
0154 } else {
0155 return {};
0156 }
0157 }
0158
0159 using param_const_iterator = ArrayRef<ParmVarDecl *>::const_iterator;
0160 param_const_iterator param_begin() const { return parameters().begin(); }
0161 param_const_iterator param_end() const { return parameters().end(); }
0162 size_t param_size() const { return parameters().size(); }
0163 bool param_empty() const { return parameters().empty(); }
0164
0165 QualType getReturnType(ASTContext &Ctx) const {
0166 switch (K) {
0167 case Function:
0168 if (E)
0169 return cast<CallExpr>(E)->getCallReturnType(Ctx);
0170 return cast<FunctionDecl>(D)->getReturnType();
0171 case ObjCMethod:
0172 if (E)
0173 return cast<ObjCMessageExpr>(E)->getCallReturnType(Ctx);
0174 return cast<ObjCMethodDecl>(D)->getReturnType();
0175 case Block:
0176
0177
0178 return cast<CallExpr>(E)->getCallReturnType(Ctx);
0179 case Destructor:
0180 case Constructor:
0181 case InheritedConstructor:
0182 case Allocator:
0183 case Deallocator:
0184 return cast<FunctionDecl>(D)->getReturnType();
0185 }
0186 llvm_unreachable("Unknown AnyCall::Kind");
0187 }
0188
0189
0190
0191 const IdentifierInfo *getIdentifier() const {
0192 if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
0193 return ND->getIdentifier();
0194 return nullptr;
0195 }
0196
0197 const Decl *getDecl() const {
0198 return D;
0199 }
0200
0201 const Expr *getExpr() const {
0202 return E;
0203 }
0204
0205 Kind getKind() const {
0206 return K;
0207 }
0208
0209 void dump() const {
0210 if (E)
0211 E->dump();
0212 if (D)
0213 D->dump();
0214 }
0215 };
0216
0217 }
0218
0219 #endif