summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/Calls.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-07-18 21:59:51 +0000
committerJordan Rose <jordan_rose@apple.com>2012-07-18 21:59:51 +0000
commit627b046c888c7d8a42e8ad345011834264f60d0e (patch)
tree3fb6e0de3abaf95219378fb332e638cea1bef60c /clang/lib/StaticAnalyzer/Core/Calls.cpp
parent9003d0d02f647431d11e0a49a2b702398761c903 (diff)
downloadbcm5719-llvm-627b046c888c7d8a42e8ad345011834264f60d0e.tar.gz
bcm5719-llvm-627b046c888c7d8a42e8ad345011834264f60d0e.zip
[analyzer] Combine all ObjC message CallEvents into ObjCMethodCall.
As pointed out by Anna, we only differentiate between explicit message sends This also adds support for ObjCSubscriptExprs, which are basically the same as properties in many ways. We were already checking these, but not emitting nice messages for them. This depends on the llvm::PointerIntPair change in r160456. llvm-svn: 160461
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/Calls.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/Calls.cpp69
1 files changed, 63 insertions, 6 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/Calls.cpp b/clang/lib/StaticAnalyzer/Core/Calls.cpp
index ba56364d513..5c161ba27b9 100644
--- a/clang/lib/StaticAnalyzer/Core/Calls.cpp
+++ b/clang/lib/StaticAnalyzer/Core/Calls.cpp
@@ -518,7 +518,7 @@ SVal ObjCMethodCall::getReceiverSVal() const {
if (!isInstanceMessage())
return UnknownVal();
- if (const Expr *Base = getInstanceReceiverExpr())
+ if (const Expr *Base = getOriginExpr()->getInstanceReceiver())
return getSVal(Base);
// An instance message with no expression means we are sending to super.
@@ -529,10 +529,67 @@ SVal ObjCMethodCall::getReceiverSVal() const {
return getState()->getSVal(getState()->getRegion(SelfDecl, LCtx));
}
-SourceRange ObjCPropertyAccess::getSourceRange() const {
- const ParentMap &PM = getLocationContext()->getParentMap();
- const ObjCMessageExpr *ME = getOriginExpr();
- const PseudoObjectExpr *PO = cast<PseudoObjectExpr>(PM.getParent(ME));
- return PO->getSourceRange();
+SourceRange ObjCMethodCall::getSourceRange() const {
+ switch (getMessageKind()) {
+ case OCM_Message:
+ return getOriginExpr()->getSourceRange();
+ case OCM_PropertyAccess:
+ case OCM_Subscript:
+ return getContainingPseudoObjectExpr()->getSourceRange();
+ }
+}
+
+typedef llvm::PointerIntPair<const PseudoObjectExpr *, 2> ObjCMessageDataTy;
+
+const PseudoObjectExpr *ObjCMethodCall::getContainingPseudoObjectExpr() const {
+ assert(Data != 0 && "Lazy lookup not yet performed.");
+ assert(getMessageKind() != OCM_Message && "Explicit message send.");
+ return ObjCMessageDataTy::getFromOpaqueValue(Data).getPointer();
+}
+
+ObjCMessageKind ObjCMethodCall::getMessageKind() const {
+ if (Data == 0) {
+ ParentMap &PM = getLocationContext()->getParentMap();
+ const Stmt *S = PM.getParent(getOriginExpr());
+ if (const PseudoObjectExpr *POE = dyn_cast_or_null<PseudoObjectExpr>(S)) {
+ const Expr *Syntactic = POE->getSyntacticForm();
+
+ // This handles the funny case of assigning to the result of a getter.
+ // This can happen if the getter returns a non-const reference.
+ if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(Syntactic))
+ Syntactic = BO->getLHS();
+
+ ObjCMessageKind K;
+ switch (Syntactic->getStmtClass()) {
+ case Stmt::ObjCPropertyRefExprClass:
+ K = OCM_PropertyAccess;
+ break;
+ case Stmt::ObjCSubscriptRefExprClass:
+ K = OCM_Subscript;
+ break;
+ default:
+ // FIXME: Can this ever happen?
+ K = OCM_Message;
+ break;
+ }
+
+ if (K != OCM_Message) {
+ const_cast<ObjCMethodCall *>(this)->Data
+ = ObjCMessageDataTy(POE, K).getOpaqueValue();
+ assert(getMessageKind() == K);
+ return K;
+ }
+ }
+
+ const_cast<ObjCMethodCall *>(this)->Data
+ = ObjCMessageDataTy(0, 1).getOpaqueValue();
+ assert(getMessageKind() == OCM_Message);
+ return OCM_Message;
+ }
+
+ ObjCMessageDataTy Info = ObjCMessageDataTy::getFromOpaqueValue(Data);
+ if (!Info.getPointer())
+ return OCM_Message;
+ return static_cast<ObjCMessageKind>(Info.getInt());
}
OpenPOWER on IntegriCloud