aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Analysis
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
commitd3933028b54ab971d36d3c1697478ef573993c0b (patch)
treec8a33021337925601dfb15cfee4c52af8917f060 /include/clang/Analysis
parentc60730eeebd5ed7caa1bb1b958f1ea0499dd829f (diff)
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
Diffstat (limited to 'include/clang/Analysis')
-rw-r--r--include/clang/Analysis/AnyCall.h54
1 files changed, 44 insertions, 10 deletions
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<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: