aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r--lib/StaticAnalyzer/Core/Calls.cpp69
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp33
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp1
3 files changed, 67 insertions, 36 deletions
diff --git a/lib/StaticAnalyzer/Core/Calls.cpp b/lib/StaticAnalyzer/Core/Calls.cpp
index ba56364d51..5c161ba27b 100644
--- a/lib/StaticAnalyzer/Core/Calls.cpp
+++ b/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());
}
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index fb99d91604..895e20eca1 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -890,35 +890,10 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::ObjCMessageExprClass: {
Bldr.takeNodes(Pred);
- // Is this a property access?
-
- const LocationContext *LCtx = Pred->getLocationContext();
- const ParentMap &PM = LCtx->getParentMap();
- const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(S);
- bool evaluated = false;
-
- if (const PseudoObjectExpr *PO =
- dyn_cast_or_null<PseudoObjectExpr>(PM.getParent(S))) {
- const Expr *syntactic = PO->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();
-
- if (const ObjCPropertyRefExpr *PR =
- dyn_cast<ObjCPropertyRefExpr>(syntactic)) {
- VisitObjCMessage(ObjCPropertyAccess(PR, PO->getSourceRange(), ME,
- Pred->getState(), LCtx),
- Pred, Dst);
- evaluated = true;
- }
- }
-
- if (!evaluated)
- VisitObjCMessage(ObjCMessageSend(ME, Pred->getState(), LCtx),
- Pred, Dst);
-
+ VisitObjCMessage(ObjCMethodCall(cast<ObjCMessageExpr>(S),
+ Pred->getState(),
+ Pred->getLocationContext()),
+ Pred, Dst);
Bldr.addNodes(Dst);
break;
}
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 493ca91b48..7cedb7ac5e 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -306,7 +306,6 @@ bool ExprEngine::inlineCall(ExplodedNodeSet &Dst,
break;
}
case CE_ObjCMessage:
- case CE_ObjCPropertyAccess:
// These always use dynamic dispatch; enabling inlining means assuming
// that a particular method will be called at runtime.
llvm_unreachable("Dynamic dispatch should be handled above.");