diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r-- | lib/StaticAnalyzer/Core/Calls.cpp | 69 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 33 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp | 1 |
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."); |