summaryrefslogtreecommitdiff
path: root/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
diff options
context:
space:
mode:
authorZancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au>2012-09-24 09:58:17 +1000
committerZancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au>2012-09-24 09:58:17 +1000
commit222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch)
tree7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
parent3d206f03985b50beacae843d880bccdc91a9f424 (diff)
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp b/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
new file mode 100644
index 0000000..65cdcd9
--- /dev/null
+++ b/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp
@@ -0,0 +1,90 @@
+//===- ObjCMessage.cpp - Wrapper for ObjC messages and dot syntax -*- C++ -*--//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ObjCMessage which serves as a common wrapper for ObjC
+// message expressions or implicit messages for loading/storing ObjC properties.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
+#include "clang/AST/DeclCXX.h"
+
+using namespace clang;
+using namespace ento;
+
+QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const {
+ QualType resultTy;
+ bool isLVal = false;
+
+ if (isObjCMessage()) {
+ resultTy = Msg.getResultType(ctx);
+ } else if (const CXXConstructExpr *Ctor =
+ CallE.dyn_cast<const CXXConstructExpr *>()) {
+ resultTy = Ctor->getType();
+ } else {
+ const CallExpr *FunctionCall = CallE.get<const CallExpr *>();
+
+ isLVal = FunctionCall->isLValue();
+ const Expr *Callee = FunctionCall->getCallee();
+ if (const FunctionDecl *FD = State->getSVal(Callee, LCtx).getAsFunctionDecl())
+ resultTy = FD->getResultType();
+ else
+ resultTy = FunctionCall->getType();
+ }
+
+ if (isLVal)
+ resultTy = ctx.getPointerType(resultTy);
+
+ return resultTy;
+}
+
+SVal CallOrObjCMessage::getFunctionCallee() const {
+ assert(isFunctionCall());
+ assert(!isCXXCall());
+ const Expr *Fun = CallE.get<const CallExpr *>()->getCallee()->IgnoreParens();
+ return State->getSVal(Fun, LCtx);
+}
+
+SVal CallOrObjCMessage::getCXXCallee() const {
+ assert(isCXXCall());
+ const CallExpr *ActualCall = CallE.get<const CallExpr *>();
+ const Expr *callee =
+ cast<CXXMemberCallExpr>(ActualCall)->getImplicitObjectArgument();
+
+ // FIXME: Will eventually need to cope with member pointers. This is
+ // a limitation in getImplicitObjectArgument().
+ if (!callee)
+ return UnknownVal();
+
+ return State->getSVal(callee, LCtx);
+}
+
+SVal
+CallOrObjCMessage::getInstanceMessageReceiver(const LocationContext *LC) const {
+ assert(isObjCMessage());
+ return Msg.getInstanceReceiverSVal(State, LC);
+}
+
+const Decl *CallOrObjCMessage::getDecl() const {
+ if (isCXXCall()) {
+ const CXXMemberCallExpr *CE =
+ cast<CXXMemberCallExpr>(CallE.dyn_cast<const CallExpr *>());
+ assert(CE);
+ return CE->getMethodDecl();
+ } else if (isObjCMessage()) {
+ return Msg.getMethodDecl();
+ } else if (isFunctionCall()) {
+ // In case of a C style call, use the path sensitive information to find
+ // the function declaration.
+ SVal CalleeVal = getFunctionCallee();
+ return CalleeVal.getAsFunctionDecl();
+ }
+ return 0;
+}
+