diff options
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h | 93 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 6 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp | 3 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 14 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp | 8 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 17 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/Calls.cpp | 15 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 22 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineObjC.cpp | 36 |
10 files changed, 136 insertions, 80 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h index 1327c8971c..fdfb485a52 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h @@ -36,7 +36,10 @@ enum CallEventKind { CE_CXXConstructor, CE_BEG_FUNCTION_CALLS = CE_Function, CE_END_FUNCTION_CALLS = CE_CXXConstructor, - CE_ObjCMessage + CE_ObjCMessage, + CE_ObjCPropertyAccess, + CE_BEG_OBJC_CALLS = CE_ObjCMessage, + CE_END_OBJC_CALLS = CE_ObjCPropertyAccess }; /// \brief Represents an abstract call to a function or method along a @@ -318,17 +321,15 @@ public: } }; -/// \brief Represents any expression that causes an Objective-C message send. -// -// This class is mostly passthrough to ObjCMessage, because /that/ class is the -// adapter for the different kinds of Objective-C messages in the system. The -// difference here is that like other CallActions this refers to a specific -// (path-sensitive) message send, while ObjCMessage is simply a wrapper for the -// various (path-insensitive) expressions that are implemented using messages. -class ObjCMessageInvocation : public CallEvent { - ObjCMessage Msg; +/// \brief Represents any expression that calls an Objective-C method. +class ObjCMethodCall : public CallEvent { + const ObjCMessageExpr *Msg; protected: + ObjCMethodCall(const ObjCMessageExpr *msg, ProgramStateRef St, + const LocationContext *LCtx, Kind K) + : CallEvent(St, LCtx, K), Msg(msg) {} + void addExtraInvalidatedRegions(RegionList &Regions) const; param_iterator param_begin() const; @@ -337,34 +338,78 @@ protected: QualType getDeclaredResultType() const; public: - ObjCMessageInvocation(const ObjCMessage &msg, ProgramStateRef St, - const LocationContext *LCtx) - : CallEvent(St, LCtx, CE_ObjCMessage), Msg(msg) {} - - Selector getSelector() const { return Msg.getSelector(); } - bool isInstanceMessage() const { return Msg.isInstanceMessage(); } - const ObjCMethodDecl *getDecl() const { return Msg.getMethodDecl(); } - unsigned getNumArgs() const { return Msg.getNumArgs(); } - const Expr *getArgExpr(unsigned Index) const { return Msg.getArgExpr(Index); } + Selector getSelector() const { return Msg->getSelector(); } + bool isInstanceMessage() const { return Msg->isInstanceMessage(); } + ObjCMethodFamily getMethodFamily() const { return Msg->getMethodFamily(); } + const ObjCMethodDecl *getDecl() const { return Msg->getMethodDecl(); } + unsigned getNumArgs() const { return Msg->getNumArgs(); } + const Expr *getArgExpr(unsigned Index) const { + return Msg->getArg(Index); + } - // FIXME: for emitting warnings and such this may not be the best idea. - const Expr *getOriginExpr() const { return Msg.getMessageExpr(); } + const ObjCMessageExpr *getOriginExpr() const { return Msg; } SVal getReceiverSVal() const; + const ObjCInterfaceDecl *getReceiverInterface() const { + return Msg->getReceiverInterface(); + } + SourceRange getReceiverSourceRange() const { - return Msg.getReceiverSourceRange(); + return Msg->getReceiverRange(); } - const ObjCInterfaceDecl *getReceiverInterface() const { - return Msg.getReceiverInterface(); + // FIXME: Remove this once everything is converted to use ObjCMethodCall. + virtual operator ObjCMessage() const { + return ObjCMessage(Msg); } static bool classof(const CallEvent *CA) { + return CA->getKind() >= CE_BEG_OBJC_CALLS && + CA->getKind() <= CE_END_OBJC_CALLS; + } +}; + +/// \brief Represents an explicit message send to an Objective-C object. +/// +/// Example: [obj descriptionWithLocale:locale]; +class ObjCMessageSend : public ObjCMethodCall { +public: + ObjCMessageSend(const ObjCMessageExpr *Msg, ProgramStateRef St, + const LocationContext *LCtx) + : ObjCMethodCall(Msg, St, LCtx, CE_ObjCMessage) {} + + static bool classof(const CallEvent *CA) { return CA->getKind() == CE_ObjCMessage; } }; +/// \brief Represents an Objective-C property getter or setter invocation. +/// +/// Example: obj.prop += 1; +class ObjCPropertyAccess : public ObjCMethodCall { + const ObjCPropertyRefExpr *PropE; + +public: + ObjCPropertyAccess(const ObjCPropertyRefExpr *pe, const ObjCMessageExpr *Msg, + const ProgramStateRef St, const LocationContext *LCtx) + : ObjCMethodCall(Msg, St, LCtx, CE_ObjCPropertyAccess), PropE(pe) {} + + /// \brief Returns true if this property access is calling the setter method. + bool isSetter() const { + return getNumArgs() > 0; + } + + // FIXME: Remove this once everything is converted to use ObjCMethodCall. + operator ObjCMessage() const { + return ObjCMessage(getOriginExpr(), PropE, isSetter()); + } + + static bool classof(const CallEvent *CA) { + return CA->getKind() == CE_ObjCPropertyAccess; + } +}; + } // end namespace ento } // end namespace clang diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 46fb70deae..bddc23cacd 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -42,7 +42,7 @@ namespace ento { class AnalysisManager; class CallEvent; -class ObjCMessage; +class ObjCMethodCall; class ExprEngine : public SubEngine { AnalysisManager &AMgr; @@ -347,7 +347,7 @@ public: void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitObjCMessage(const ObjCMessage &msg, ExplodedNode *Pred, + void VisitObjCMessage(const ObjCMethodCall &Msg, ExplodedNode *Pred, ExplodedNodeSet &Dst); /// VisitReturnStmt - Transfer function logic for return statements. @@ -433,7 +433,7 @@ public: } protected: - void evalObjCMessage(StmtNodeBuilder &Bldr, const ObjCMessage &msg, + void evalObjCMessage(StmtNodeBuilder &Bldr, const ObjCMethodCall &Msg, ExplodedNode *Pred, ProgramStateRef state, bool GenSink); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h index e567d2d498..f64326d2c6 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h @@ -53,7 +53,7 @@ public: return IsPropSetter; } - const Expr *getMessageExpr() const { + const ObjCMessageExpr *getMessageExpr() const { return Msg; } diff --git a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index 11a9ab373c..30be60c9a6 100644 --- a/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -300,7 +300,8 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg, "Argument for property setter is an uninitialized value" : "Argument in message expression is an uninitialized value"; // Check for any arguments that are uninitialized/undefined. - PreVisitProcessArgs(C, ObjCMessageInvocation(msg, state, LCtx), + // FIXME: ObjCMessage is set to be removed soon. + PreVisitProcessArgs(C, ObjCMessageSend(msg.getMessageExpr(), state, LCtx), bugDesc, BT_msg_arg); } diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 29bb9c8f25..2c960921a4 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -481,8 +481,8 @@ void MallocChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { C.addTransition(State); } -static bool isFreeWhenDoneSetToZero(const ObjCMessageInvocation &Call, - Selector &S) { +static bool isFreeWhenDoneSetToZero(const ObjCMethodCall &Call) { + Selector S = Call.getSelector(); for (unsigned i = 1; i < S.getNumArgs(); ++i) if (S.getNameForSlot(i).equals("freeWhenDone")) if (Call.getArgSVal(i).isConstant(0)) @@ -497,7 +497,9 @@ void MallocChecker::checkPreObjCMessage(const ObjCMessage &Msg, if (!MD) return; - ObjCMessageInvocation Call(Msg, C.getState(), C.getLocationContext()); + // FIXME: ObjCMessage is going away soon. + ObjCMessageSend Call(Msg.getMessageExpr(), C.getState(), + C.getLocationContext()); Selector S = Msg.getSelector(); // If the first selector is dataWithBytesNoCopy, assume that the memory will @@ -508,7 +510,7 @@ void MallocChecker::checkPreObjCMessage(const ObjCMessage &Msg, if ((S.getNameForSlot(0) == "dataWithBytesNoCopy" || S.getNameForSlot(0) == "initWithBytesNoCopy" || S.getNameForSlot(0) == "initWithCharactersNoCopy") && - !isFreeWhenDoneSetToZero(Call, S)){ + !isFreeWhenDoneSetToZero(Call)){ unsigned int argIdx = 0; C.addTransition(FreeMemAux(C, Call.getArgExpr(argIdx), Msg.getMessageExpr(), C.getState(), true)); @@ -1322,11 +1324,11 @@ bool MallocChecker::doesNotFreeMemory(const CallEvent *Call, // TODO: If we want to be more optimistic here, we'll need to make sure that // regions escape to C++ containers. They seem to do that even now, but for // mysterious reasons. - if (!(isa<FunctionCall>(Call) || isa<ObjCMessageInvocation>(Call))) + if (!(isa<FunctionCall>(Call) || isa<ObjCMethodCall>(Call))) return false; // Check Objective-C messages by selector name. - if (const ObjCMessageInvocation *Msg = dyn_cast<ObjCMessageInvocation>(Call)){ + if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(Call)) { // If it's not a framework call, or if it takes a callback, assume it // can free memory. if (!Call->isInSystemHeader() || Call->hasNonZeroCallbackArg()) diff --git a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index bb6ab6f2e3..c25da87405 100644 --- a/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -209,7 +209,9 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg, return; } - ObjCMessageInvocation MsgWrapper(msg, C.getState(), C.getLocationContext()); + // FIXME: ObjCMessage is going away. + ObjCMessageSend MsgWrapper(msg.getMessageExpr(), C.getState(), + C.getLocationContext()); checkPostStmt(MsgWrapper, C); // We don't check for an invalid 'self' in an obj-c message expression to cut @@ -300,7 +302,9 @@ void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE, void ObjCSelfInitChecker::checkPreObjCMessage(ObjCMessage Msg, CheckerContext &C) const { - ObjCMessageInvocation MsgWrapper(Msg, C.getState(), C.getLocationContext()); + // FIXME: ObjCMessage is going away. + ObjCMessageSend MsgWrapper(Msg.getMessageExpr(), C.getState(), + C.getLocationContext()); checkPreStmt(MsgWrapper, C); } diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index d43b2cde26..12b74e7e29 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -747,10 +747,10 @@ public: QualType RetTy, ObjCMethodSummariesTy &CachedSummaries); - const RetainSummary *getInstanceMethodSummary(const ObjCMessageInvocation &M, + const RetainSummary *getInstanceMethodSummary(const ObjCMethodCall &M, ProgramStateRef State); - const RetainSummary *getClassMethodSummary(const ObjCMessageInvocation &M) { + const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) { assert(!M.isInstanceMessage()); const ObjCInterfaceDecl *Class = M.getReceiverInterface(); @@ -950,8 +950,9 @@ RetainSummaryManager::getSummary(const CallEvent &Call, case CE_CXXConstructor: // FIXME: These calls are currently unsupported. return getPersistentStopSummary(); - case CE_ObjCMessage: { - const ObjCMessageInvocation &Msg = cast<ObjCMessageInvocation>(Call); + case CE_ObjCMessage: + case CE_ObjCPropertyAccess: { + const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call); if (Msg.isInstanceMessage()) Summ = getInstanceMethodSummary(Msg, State); else @@ -1447,7 +1448,7 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD, } const RetainSummary * -RetainSummaryManager::getInstanceMethodSummary(const ObjCMessageInvocation &Msg, +RetainSummaryManager::getInstanceMethodSummary(const ObjCMethodCall &Msg, ProgramStateRef State) { const ObjCInterfaceDecl *ReceiverClass = 0; @@ -2795,7 +2796,8 @@ void RetainCountChecker::checkPostObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const { ProgramStateRef state = C.getState(); const LocationContext *LC = C.getLocationContext(); - ObjCMessageInvocation Call(Msg, state, LC); + // FIXME: ObjCMessage is going away. + ObjCMessageSend Call(Msg.getMessageExpr(), state, LC); RetainSummaryManager &Summaries = getSummaryManager(C); const RetainSummary *Summ = Summaries.getSummary(Call, state); @@ -2859,8 +2861,7 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ, // Evaluate the effect on the message receiver. bool ReceiverIsTracked = false; if (!hasErr) { - const ObjCMessageInvocation *MsgInvocation = - dyn_cast<ObjCMessageInvocation>(&CallOrMsg); + const ObjCMethodCall *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg); if (MsgInvocation) { if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) { if (const RefVal *T = state->get<RefBindings>(Sym)) { diff --git a/lib/StaticAnalyzer/Core/Calls.cpp b/lib/StaticAnalyzer/Core/Calls.cpp index 510f8340a2..bdd4508cea 100644 --- a/lib/StaticAnalyzer/Core/Calls.cpp +++ b/lib/StaticAnalyzer/Core/Calls.cpp @@ -334,7 +334,7 @@ void CXXConstructorCall::addExtraInvalidatedRegions(RegionList &Regions) const { } -CallEvent::param_iterator ObjCMessageInvocation::param_begin() const { +CallEvent::param_iterator ObjCMethodCall::param_begin() const { const ObjCMethodDecl *D = getDecl(); if (!D) return 0; @@ -342,7 +342,7 @@ CallEvent::param_iterator ObjCMessageInvocation::param_begin() const { return D->param_begin(); } -CallEvent::param_iterator ObjCMessageInvocation::param_end() const { +CallEvent::param_iterator ObjCMethodCall::param_end() const { const ObjCMethodDecl *D = getDecl(); if (!D) return 0; @@ -351,12 +351,12 @@ CallEvent::param_iterator ObjCMessageInvocation::param_end() const { } void -ObjCMessageInvocation::addExtraInvalidatedRegions(RegionList &Regions) const { +ObjCMethodCall::addExtraInvalidatedRegions(RegionList &Regions) const { if (const MemRegion *R = getReceiverSVal().getAsRegion()) Regions.push_back(R); } -QualType ObjCMessageInvocation::getDeclaredResultType() const { +QualType ObjCMethodCall::getDeclaredResultType() const { const ObjCMethodDecl *D = getDecl(); if (!D) return QualType(); @@ -364,12 +364,12 @@ QualType ObjCMessageInvocation::getDeclaredResultType() const { return D->getResultType(); } -SVal ObjCMessageInvocation::getReceiverSVal() const { +SVal ObjCMethodCall::getReceiverSVal() const { // FIXME: Is this the best way to handle class receivers? if (!isInstanceMessage()) return UnknownVal(); - const Expr *Base = Msg.getInstanceReceiver(); + const Expr *Base = Msg->getInstanceReceiver(); if (Base) return getSVal(Base); @@ -377,5 +377,6 @@ SVal ObjCMessageInvocation::getReceiverSVal() const { // In this case the object reference is the same as 'self'. const ImplicitParamDecl *SelfDecl = LCtx->getSelfDecl(); assert(SelfDecl && "No message receiver Expr, but not in an ObjC method"); - return loc::MemRegionVal(State->getRegion(SelfDecl, LCtx)); + return State->getSVal(State->getRegion(SelfDecl, LCtx)); } + diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 255d870186..141c5bbf03 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -867,26 +867,32 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::ObjCMessageExprClass: { Bldr.takeNodes(Pred); // Is this a property access? - const ParentMap &PM = Pred->getLocationContext()->getParentMap(); + + 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))) { + 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)) { - bool isSetter = ME->getNumArgs() > 0; - VisitObjCMessage(ObjCMessage(ME, PR, isSetter), Pred, Dst); + VisitObjCMessage(ObjCPropertyAccess(PR, ME, Pred->getState(), LCtx), + Pred, Dst); evaluated = true; } - else if (isa<BinaryOperator>(syntactic)) { - VisitObjCMessage(ObjCMessage(ME, 0, true), Pred, Dst); - } } if (!evaluated) - VisitObjCMessage(ME, Pred, Dst); + VisitObjCMessage(ObjCMessageSend(ME, Pred->getState(), LCtx), + Pred, Dst); Bldr.addNodes(Dst); break; diff --git a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp index d35d999b5e..86630a8c02 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp @@ -141,7 +141,7 @@ static bool isSubclass(const ObjCInterfaceDecl *Class, IdentifierInfo *II) { return isSubclass(Class->getSuperClass(), II); } -void ExprEngine::VisitObjCMessage(const ObjCMessage &msg, +void ExprEngine::VisitObjCMessage(const ObjCMethodCall &msg, ExplodedNode *Pred, ExplodedNodeSet &Dst) { @@ -160,18 +160,20 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg, ExplodedNode *Pred = *DI; bool RaisesException = false; - if (const Expr *Receiver = msg.getInstanceReceiver()) { - ProgramStateRef state = Pred->getState(); - SVal recVal = state->getSVal(Receiver, Pred->getLocationContext()); + if (msg.isInstanceMessage()) { + SVal recVal = msg.getReceiverSVal(); if (!recVal.isUndef()) { // Bifurcate the state into nil and non-nil ones. DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal); + ProgramStateRef state = Pred->getState(); ProgramStateRef notNilState, nilState; llvm::tie(notNilState, nilState) = state->assume(receiverVal); // There are three cases: can be nil or non-nil, must be nil, must be // non-nil. We ignore must be nil, and merge the rest two into non-nil. + // FIXME: This ignores many potential bugs (<rdar://problem/11733396>). + // Revisit once we have lazier constraints. if (nilState && !notNilState) { continue; } @@ -186,12 +188,9 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg, // Dispatch to plug-in transfer function. evalObjCMessage(Bldr, msg, Pred, notNilState, RaisesException); } - } else if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) { - // Note that this branch also handles messages to super, not just - // class methods! - + } else { // Check for special class methods. - if (!msg.isInstanceMessage()) { + if (const ObjCInterfaceDecl *Iface = msg.getReceiverInterface()) { if (!NSExceptionII) { ASTContext &Ctx = getContext(); NSExceptionII = &Ctx.Idents.get("NSException"); @@ -243,13 +242,10 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg, } void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr, - const ObjCMessage &msg, + const ObjCMethodCall &msg, ExplodedNode *Pred, ProgramStateRef state, bool GenSink) { - const LocationContext *LCtx = Pred->getLocationContext(); - unsigned BlockCount = currentBuilderContext->getCurrentBlockCount(); - // First handle the return value. SVal ReturnValue = UnknownVal(); @@ -261,17 +257,18 @@ void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr, case OMF_retain: case OMF_self: { // These methods return their receivers. - const Expr *ReceiverE = msg.getInstanceReceiver(); - if (ReceiverE) - ReturnValue = state->getSVal(ReceiverE, LCtx); + ReturnValue = msg.getReceiverSVal(); break; } } + const LocationContext *LCtx = Pred->getLocationContext(); + unsigned BlockCount = currentBuilderContext->getCurrentBlockCount(); + // If we failed to figure out the return value, use a conjured value instead. if (ReturnValue.isUnknown()) { SValBuilder &SVB = getSValBuilder(); - QualType ResultTy = msg.getResultType(getContext()); + QualType ResultTy = msg.getResultType(); const Expr *CurrentE = cast<Expr>(currentStmt); ReturnValue = SVB.getConjuredSymbolVal(NULL, CurrentE, LCtx, ResultTy, BlockCount); @@ -281,11 +278,10 @@ void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr, state = state->BindExpr(currentStmt, LCtx, ReturnValue); // Invalidate the arguments (and the receiver) - ObjCMessageInvocation Invocation(msg, state, LCtx); - state = Invocation.invalidateRegions(BlockCount); + state = msg.invalidateRegions(BlockCount, state); // And create the new node. - Bldr.generateNode(msg.getMessageExpr(), Pred, state, GenSink); + Bldr.generateNode(msg.getOriginExpr(), Pred, state, GenSink); assert(Bldr.hasGeneratedNodes()); } |