From: George Karpenkov Date: Tue, 29 Jan 2019 19:29:19 +0000 (+0000) Subject: Extend AnyCall to handle callable declarations without the call expressions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d3933028b54ab971d36d3c1697478ef573993c0b;p=clang Extend AnyCall to handle callable declarations without the call expressions That weakens inner invariants, but allows the class to be more generic, allowing usage in situations where the call expression is not known (or should not matter). Differential Revision: https://reviews.llvm.org/D57344 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@352531 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/AnyCall.h b/include/clang/Analysis/AnyCall.h index f3442df6a2..a9098adcbf 100644 --- a/include/clang/Analysis/AnyCall.h +++ b/include/clang/Analysis/AnyCall.h @@ -19,7 +19,9 @@ namespace clang { -/// An instance of this class corresponds to a 'callable' call. +/// An instance of this class corresponds to a call. +/// It might be a syntactically-concrete call, done as a part of evaluating an +/// expression, or it may be an abstract callee with no associated expression. class AnyCall { public: enum Kind { @@ -48,7 +50,11 @@ public: }; private: - /// Call expression, remains null iff the call is an implicit destructor call. + /// Either expression or declaration (but not both at the same time) + /// can be null. + + /// Call expression, is null when is not known (then declaration is non-null), + /// or for implicit destructor calls (when no expression exists.) const Expr *E = nullptr; /// Corresponds to a statically known declaration of the called function, @@ -56,8 +62,6 @@ private: const Decl *D = nullptr; Kind K; - AnyCall(const Expr *E, const Decl *D, Kind K) : E(E), D(D), K(K) {} - public: AnyCall(const CallExpr *CE) : E(CE) { D = CE->getCalleeDecl(); @@ -80,6 +84,23 @@ public: AnyCall(const CXXConstructExpr *NE) : E(NE), D(NE->getConstructor()), K(Constructor) {} + AnyCall(const CXXDestructorDecl *D) : E(nullptr), D(D), K(Destructor) {} + + AnyCall(const CXXConstructorDecl *D) : E(nullptr), D(D), K(Constructor) {} + + AnyCall(const ObjCMethodDecl *D) : E(nullptr), D(D), K(ObjCMethod) {} + + AnyCall(const FunctionDecl *D) : E(nullptr), D(D) { + if (isa(D)) { + K = Constructor; + } else if (isa (D)) { + K = Destructor; + } else { + K = Function; + } + + } + /// If {@code E} is a generic call (to ObjC method /function/block/etc), /// return a constructed {@code AnyCall} object. Return None otherwise. static Optional forExpr(const Expr *E) { @@ -98,8 +119,16 @@ public: } } - static AnyCall forDestructorCall(const CXXDestructorDecl *D) { - return AnyCall(/*E=*/nullptr, D, Destructor); + /// If {@code D} is a callable (Objective-C method or a function), return + /// a constructed {@code AnyCall} object. Return None otherwise. + // FIXME: block support. + static Optional forDecl(const Decl *D) { + if (const auto *FD = dyn_cast(D)) { + return AnyCall(FD); + } else if (const auto *MD = dyn_cast(D)) { + return AnyCall(MD); + } + return None; } /// \returns formal parameters for direct calls (including virtual calls) @@ -111,8 +140,6 @@ public: return FD->parameters(); } else if (const auto *MD = dyn_cast(D)) { return MD->parameters(); - } else if (const auto *CD = dyn_cast(D)) { - return CD->parameters(); } else if (const auto *BD = dyn_cast(D)) { return BD->parameters(); } else { @@ -129,10 +156,17 @@ public: QualType getReturnType(ASTContext &Ctx) const { switch (K) { case Function: + if (E) + return cast(E)->getCallReturnType(Ctx); + return cast(D)->getReturnType(); + case ObjCMethod: + if (E) + return cast(E)->getCallReturnType(Ctx); + return cast(D)->getReturnType(); case Block: + // FIXME: BlockDecl does not know its return type, + // hence the asymmetry with the function and method cases above. return cast(E)->getCallReturnType(Ctx); - case ObjCMethod: - return cast(E)->getCallReturnType(Ctx); case Destructor: case Constructor: case Allocator: diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp index c3d191429e..1ab4106b85 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp @@ -347,7 +347,7 @@ const static RetainSummary *getSummary(RetainSummaryManager &Summaries, const Expr *CE = Call.getOriginExpr(); AnyCall C = CE ? *AnyCall::forExpr(CE) - : AnyCall::forDestructorCall(cast(Call.getDecl())); + : AnyCall(cast(Call.getDecl())); return Summaries.getSummary(C, Call.hasNonZeroCallbackArg(), isReceiverUnconsumedSelf(Call), ReceiverType); }