summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2019-01-29 19:29:19 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2019-01-29 19:29:19 +0000
commit38bc347ff50b80558a8c1e7e2156057c0033cf7f (patch)
treef4584bdae754db3779a941fc649f4b861ade4c30 /clang
parent0f3bbbaec98c891b33409ce27e8bf550b0d60d85 (diff)
downloadbcm5719-llvm-38bc347ff50b80558a8c1e7e2156057c0033cf7f.tar.gz
bcm5719-llvm-38bc347ff50b80558a8c1e7e2156057c0033cf7f.zip
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 llvm-svn: 352531
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Analysis/AnyCall.h54
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp2
2 files changed, 45 insertions, 11 deletions
diff --git a/clang/include/clang/Analysis/AnyCall.h b/clang/include/clang/Analysis/AnyCall.h
index f3442df6a25..a9098adcbfa 100644
--- a/clang/include/clang/Analysis/AnyCall.h
+++ b/clang/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<CXXConstructorDecl>(D)) {
+ K = Constructor;
+ } else if (isa <CXXDestructorDecl>(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<AnyCall> 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<AnyCall> forDecl(const Decl *D) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ return AnyCall(FD);
+ } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(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<ObjCMethodDecl>(D)) {
return MD->parameters();
- } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
- return CD->parameters();
} else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
return BD->parameters();
} else {
@@ -129,10 +156,17 @@ public:
QualType getReturnType(ASTContext &Ctx) const {
switch (K) {
case Function:
+ if (E)
+ return cast<CallExpr>(E)->getCallReturnType(Ctx);
+ return cast<FunctionDecl>(D)->getReturnType();
+ case ObjCMethod:
+ if (E)
+ return cast<ObjCMessageExpr>(E)->getCallReturnType(Ctx);
+ return cast<ObjCMethodDecl>(D)->getReturnType();
case Block:
+ // FIXME: BlockDecl does not know its return type,
+ // hence the asymmetry with the function and method cases above.
return cast<CallExpr>(E)->getCallReturnType(Ctx);
- case ObjCMethod:
- return cast<ObjCMessageExpr>(E)->getCallReturnType(Ctx);
case Destructor:
case Constructor:
case Allocator:
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
index c3d191429e4..1ab4106b857 100644
--- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
+++ b/clang/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<CXXDestructorDecl>(Call.getDecl()));
+ : AnyCall(cast<CXXDestructorDecl>(Call.getDecl()));
return Summaries.getSummary(C, Call.hasNonZeroCallbackArg(),
isReceiverUnconsumedSelf(Call), ReceiverType);
}
OpenPOWER on IntegriCloud