[cfe-commits] r159558 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/ lib/StaticAnalyzer/Checkers/ lib/StaticAnalyzer/Core/

Jordan Rose jordan_rose at apple.com
Mon Jul 2 12:27:56 PDT 2012


Author: jrose
Date: Mon Jul  2 14:27:56 2012
New Revision: 159558

URL: http://llvm.org/viewvc/llvm-project?rev=159558&view=rev
Log:
[analyzer] Begin replacing ObjCMessage with ObjCMethodCall and friends.

Previously, the CallEvent subclass ObjCMessageInvocation was just a wrapper
around the existing ObjCMessage abstraction (over message sends and property
accesses). Now, we have abstract CallEvent ObjCMethodCall with subclasses
ObjCMessageSend and ObjCPropertyAccess.

In addition to removing yet another wrapper object, this should make it easy
to add a ObjCSubscriptAccess call event soon.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/Calls.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h?rev=159558&r1=159557&r2=159558&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h Mon Jul  2 14:27:56 2012
@@ -36,7 +36,10 @@
   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 @@
   }
 };
 
-/// \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 @@
   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
 

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=159558&r1=159557&r2=159558&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Mon Jul  2 14:27:56 2012
@@ -42,7 +42,7 @@
 
 class AnalysisManager;
 class CallEvent;
-class ObjCMessage;
+class ObjCMethodCall;
 
 class ExprEngine : public SubEngine {
   AnalysisManager &AMgr;
@@ -347,7 +347,7 @@
   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 @@
   }
   
 protected:
-  void evalObjCMessage(StmtNodeBuilder &Bldr, const ObjCMessage &msg,
+  void evalObjCMessage(StmtNodeBuilder &Bldr, const ObjCMethodCall &Msg,
                        ExplodedNode *Pred, ProgramStateRef state,
                        bool GenSink);
 

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h?rev=159558&r1=159557&r2=159558&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h Mon Jul  2 14:27:56 2012
@@ -53,7 +53,7 @@
     return IsPropSetter;
   }
 
-  const Expr *getMessageExpr() const { 
+  const ObjCMessageExpr *getMessageExpr() const {
     return Msg;
   }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp?rev=159558&r1=159557&r2=159558&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp Mon Jul  2 14:27:56 2012
@@ -300,7 +300,8 @@
                      "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);
 }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=159558&r1=159557&r2=159558&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Mon Jul  2 14:27:56 2012
@@ -481,8 +481,8 @@
   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 @@
   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 @@
   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 @@
   // 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())

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp?rev=159558&r1=159557&r2=159558&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp Mon Jul  2 14:27:56 2012
@@ -209,7 +209,9 @@
     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::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);
 }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=159558&r1=159557&r2=159558&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Mon Jul  2 14:27:56 2012
@@ -747,10 +747,10 @@
                                         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 @@
   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 @@
 }
 
 const RetainSummary *
-RetainSummaryManager::getInstanceMethodSummary(const ObjCMessageInvocation &Msg,
+RetainSummaryManager::getInstanceMethodSummary(const ObjCMethodCall &Msg,
                                                ProgramStateRef State) {
   const ObjCInterfaceDecl *ReceiverClass = 0;
 
@@ -2795,7 +2796,8 @@
                                               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 @@
   // 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)) {

Modified: cfe/trunk/lib/StaticAnalyzer/Core/Calls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Calls.cpp?rev=159558&r1=159557&r2=159558&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Calls.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Calls.cpp Mon Jul  2 14:27:56 2012
@@ -334,7 +334,7 @@
 }
 
 
-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 @@
   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 @@
 }
 
 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 @@
   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 @@
   // 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));
 }
+

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=159558&r1=159557&r2=159558&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Mon Jul  2 14:27:56 2012
@@ -867,26 +867,32 @@
     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;

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp?rev=159558&r1=159557&r2=159558&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp Mon Jul  2 14:27:56 2012
@@ -141,7 +141,7 @@
   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 @@
     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 @@
         // 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::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 @@
   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 @@
   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());
 }
 





More information about the cfe-commits mailing list