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

Argyrios Kyrtzidis akyrtzi at gmail.com
Mon Jan 24 16:03:53 PST 2011


Author: akirtzidis
Date: Mon Jan 24 18:03:53 2011
New Revision: 124159

URL: http://llvm.org/viewvc/llvm-project?rev=124159&view=rev
Log:
[analyzer] Introduce ObjCMessage which represents both explicit ObjC message expressions and implicit
messages that are sent for handling properties in dot syntax.

Replace all direct uses of ObjCMessageExpr in the checkers and checker interface with ObjCMessage.

Added:
    cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ObjCMessage.h
    cfe/trunk/lib/StaticAnalyzer/ObjCMessage.cpp
Modified:
    cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/Checker.h
    cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/CheckerVisitor.def
    cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/TransferFuncs.h
    cfe/trunk/lib/StaticAnalyzer/CFRefCount.cpp
    cfe/trunk/lib/StaticAnalyzer/CMakeLists.txt
    cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/Checker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/Checker.h?rev=124159&r1=124158&r2=124159&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/Checker.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/Checker.h Mon Jan 24 18:03:53 2011
@@ -203,12 +203,26 @@
       _PostVisit(C, S);
   }
 
+  void GR_visitObjCMessage(ExplodedNodeSet &Dst,
+                           StmtNodeBuilder &Builder,
+                           ExprEngine &Eng,
+                           const ObjCMessage &msg,
+                           ExplodedNode *Pred, void *tag, bool isPrevisit) {
+    CheckerContext C(Dst, Builder, Eng, Pred, tag,
+                     isPrevisit ? ProgramPoint::PreStmtKind :
+                     ProgramPoint::PostStmtKind, 0, msg.getOriginExpr());
+    if (isPrevisit)
+      preVisitObjCMessage(C, msg);
+    else
+      postVisitObjCMessage(C, msg);
+  }
+
   bool GR_evalNilReceiver(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder,
-                          ExprEngine &Eng, const ObjCMessageExpr *ME,
+                          ExprEngine &Eng, const ObjCMessage &msg,
                           ExplodedNode *Pred, const GRState *state, void *tag) {
     CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind,
-                     0, ME, state);
-    return evalNilReceiver(C, ME);
+                     0, msg.getOriginExpr(), state);
+    return evalNilReceiver(C, msg);
   }
 
   bool GR_evalCallExpr(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder,
@@ -258,6 +272,8 @@
   virtual ~Checker();
   virtual void _PreVisit(CheckerContext &C, const Stmt *S) {}
   virtual void _PostVisit(CheckerContext &C, const Stmt *S) {}
+  virtual void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg) {}
+  virtual void postVisitObjCMessage(CheckerContext &C, ObjCMessage msg) {}
   virtual void visitLocation(CheckerContext &C, const Stmt *S, SVal location,
                              bool isLoad) {}
   virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
@@ -272,7 +288,7 @@
                                     ExprEngine &Eng,
                                     const Stmt *Condition, void *tag) {}
 
-  virtual bool evalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) {
+  virtual bool evalNilReceiver(CheckerContext &C, ObjCMessage msg) {
     return false;
   }
 

Modified: cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/CheckerVisitor.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/CheckerVisitor.def?rev=124159&r1=124158&r2=124159&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/CheckerVisitor.def (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/CheckerVisitor.def Mon Jan 24 18:03:53 2011
@@ -34,7 +34,6 @@
 PREVISIT(DeclStmt, Stmt)
 PREVISIT(ImplicitCastExpr, CastExpr)
 PREVISIT(ObjCAtSynchronizedStmt, Stmt)
-PREVISIT(ObjCMessageExpr, Stmt)
 PREVISIT(ReturnStmt, Stmt)
 
 POSTVISIT(BlockExpr, Stmt)
@@ -43,7 +42,6 @@
 POSTVISIT(CompoundAssignOperator, BinaryOperator)
 POSTVISIT(CXXOperatorCallExpr, GenericCall)
 POSTVISIT(CXXMemberCallExpr, GenericCall)
-POSTVISIT(ObjCMessageExpr, Stmt)
 POSTVISIT(ObjCIvarRefExpr, Stmt)
 
 #undef PREVISIT

Modified: cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h?rev=124159&r1=124158&r2=124159&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h Mon Jan 24 18:03:53 2011
@@ -282,11 +282,14 @@
   void CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, 
                     CallbackKind Kind);
 
+  void CheckerVisitObjCMessage(const ObjCMessage &msg, ExplodedNodeSet &Dst,
+                               ExplodedNodeSet &Src, bool isPrevisit);
+
   bool CheckerEvalCall(const CallExpr *CE, 
                        ExplodedNodeSet &Dst, 
                        ExplodedNode *Pred);
 
-  void CheckerEvalNilReceiver(const ObjCMessageExpr *ME, 
+  void CheckerEvalNilReceiver(const ObjCMessage &msg,
                               ExplodedNodeSet &Dst,
                               const GRState *state,
                               ExplodedNode *Pred);
@@ -490,10 +493,10 @@
   }
   
 protected:
-  void evalObjCMessageExpr(ExplodedNodeSet& Dst, const ObjCMessageExpr* ME, 
-                           ExplodedNode* Pred, const GRState *state) {
+  void evalObjCMessage(ExplodedNodeSet& Dst, const ObjCMessage &msg, 
+                       ExplodedNode* Pred, const GRState *state) {
     assert (Builder && "StmtNodeBuilder must be defined.");
-    getTF().evalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state);
+    getTF().evalObjCMessage(Dst, *this, *Builder, msg, Pred, state);
   }
 
   const GRState* MarkBranch(const GRState* St, const Stmt* Terminator,

Added: cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ObjCMessage.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ObjCMessage.h?rev=124159&view=auto
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ObjCMessage.h (added)
+++ cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ObjCMessage.h Mon Jan 24 18:03:53 2011
@@ -0,0 +1,207 @@
+//===- ObjCMessage.h - Wrapper for ObjC messages and dot syntax ---*- C++ -*--//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ObjCMessage which serves as a common wrapper for ObjC
+// message expressions or implicit messages for loading/storing ObjC properties.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
+#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_OBJCMESSAGE
+
+#include "clang/StaticAnalyzer/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/PathSensitive/GRState.h"
+#include "clang/AST/ExprObjC.h"
+
+namespace clang {
+namespace ento {
+
+/// \brief Represents both explicit ObjC message expressions and implicit
+/// messages that are sent for handling properties in dot syntax.
+class ObjCMessage {
+  const Expr *MsgOrPropE;
+  const Expr *OriginE;
+  bool IsPropSetter;
+  SVal SetterArgV;
+
+protected:
+  ObjCMessage(const Expr *E, const Expr *origE, bool isSetter, SVal setArgV)
+    : MsgOrPropE(E), OriginE(origE),
+      IsPropSetter(isSetter), SetterArgV(setArgV) { }
+
+public:
+  ObjCMessage() : MsgOrPropE(0), OriginE(0) { }
+
+  ObjCMessage(const ObjCMessageExpr *E)
+    : MsgOrPropE(E), OriginE(E) {
+    assert(E && "should not be initialized with null expression");
+  }
+
+  bool isValid() const { return MsgOrPropE != 0; }
+  bool isInvalid() const { return !isValid(); }
+
+  bool isMessageExpr() const {
+    return isValid() && isa<ObjCMessageExpr>(MsgOrPropE);
+  }
+
+  bool isPropertyGetter() const {
+    return isValid() &&
+           isa<ObjCPropertyRefExpr>(MsgOrPropE) && !IsPropSetter;
+  }
+
+  bool isPropertySetter() const {
+    return isValid() &&
+           isa<ObjCPropertyRefExpr>(MsgOrPropE) && IsPropSetter;
+  }
+  
+  const Expr *getOriginExpr() const { return OriginE; }
+
+  QualType getType(ASTContext &ctx) const;
+
+  QualType getResultType(ASTContext &ctx) const {
+    assert(isValid() && "This ObjCMessage is uninitialized!");
+    if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+      if (const ObjCMethodDecl *MD = msgE->getMethodDecl())
+        return MD->getResultType();
+    return getType(ctx);
+  }
+
+  Selector getSelector() const;
+
+  const Expr *getInstanceReceiver() const {
+    assert(isValid() && "This ObjCMessage is uninitialized!");
+    if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+      return msgE->getInstanceReceiver();
+    return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getBase();
+  }
+
+  bool isInstanceMessage() const {
+    assert(isValid() && "This ObjCMessage is uninitialized!");
+    if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+      return msgE->isInstanceMessage();
+    const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+    // FIXME: 'super' may be super class.
+    return propE->isObjectReceiver() || propE->isSuperReceiver();
+  }
+
+  const ObjCMethodDecl *getMethodDecl() const;
+  
+  const ObjCInterfaceDecl *getReceiverInterface() const;
+
+  SourceLocation getSuperLoc() const {
+    assert(isValid() && "This ObjCMessage is uninitialized!");
+    if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+      return msgE->getSuperLoc();
+    return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getReceiverLocation();
+  }
+
+   SourceRange getSourceRange() const {
+     assert(isValid() && "This ObjCMessage is uninitialized!");
+    return MsgOrPropE->getSourceRange();
+  }
+
+   unsigned getNumArgs() const {
+     assert(isValid() && "This ObjCMessage is uninitialized!");
+     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+       return msgE->getNumArgs();
+     return isPropertySetter() ? 1 : 0;
+   }
+
+   SVal getArgSVal(unsigned i, const GRState *state) const {
+     assert(isValid() && "This ObjCMessage is uninitialized!");
+     assert(i < getNumArgs() && "Invalid index for argument");
+     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+       return state->getSVal(msgE->getArg(i));
+     assert(isPropertySetter());
+     return SetterArgV;
+   }
+
+   QualType getArgType(unsigned i) const {
+     assert(isValid() && "This ObjCMessage is uninitialized!");
+     assert(i < getNumArgs() && "Invalid index for argument");
+     if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+       return msgE->getArg(i)->getType();
+     assert(isPropertySetter());
+     return cast<ObjCPropertyRefExpr>(MsgOrPropE)->getType();
+   }
+   
+   const Expr *getArgExpr(unsigned i) const;
+
+   SourceRange getArgSourceRange(unsigned i) const {
+     assert(isValid() && "This ObjCMessage is uninitialized!");
+     assert(i < getNumArgs() && "Invalid index for argument");
+     if (const Expr *argE = getArgExpr(i))
+       return argE->getSourceRange();
+     return OriginE->getSourceRange();
+   }
+};
+
+class ObjCPropertyGetter : public ObjCMessage {
+public:
+  ObjCPropertyGetter(const ObjCPropertyRefExpr *propE, const Expr *originE)
+    : ObjCMessage(propE, originE, false, SVal()) {
+    assert(propE && originE &&
+           "should not be initialized with null expressions");
+  }
+};
+
+class ObjCPropertySetter : public ObjCMessage {
+public:
+  ObjCPropertySetter(const ObjCPropertyRefExpr *propE, const Expr *storeE,
+                     SVal argV)
+    : ObjCMessage(propE, storeE, true, argV) {
+    assert(propE && storeE &&"should not be initialized with null expressions");
+  }
+};
+
+/// \brief Common wrapper for a call expression or an ObjC message, mainly to
+/// provide a common interface for handling their arguments.
+class CallOrObjCMessage {
+  const CallExpr *CallE;
+  ObjCMessage Msg;
+  const GRState *State;
+  
+public:
+  CallOrObjCMessage(const CallExpr *callE, const GRState *state)
+    : CallE(callE), State(state) { }
+  CallOrObjCMessage(const ObjCMessage &msg, const GRState *state)
+    : CallE(0), Msg(msg), State(state) { }
+
+  QualType getResultType(ASTContext &ctx) const;
+
+  unsigned getNumArgs() const {
+    if (CallE) return CallE->getNumArgs();
+    return Msg.getNumArgs();
+  }
+
+  SVal getArgSVal(unsigned i) const {
+    assert(i < getNumArgs());
+    if (CallE) return State->getSVal(CallE->getArg(i));
+    return Msg.getArgSVal(i, State);
+  }
+
+  SVal getArgSValAsScalarOrLoc(unsigned i) const;
+
+  const Expr *getArg(unsigned i) const {
+    assert(i < getNumArgs());
+    if (CallE) return CallE->getArg(i);
+    return Msg.getArgExpr(i);
+  }
+
+  SourceRange getArgSourceRange(unsigned i) const {
+    assert(i < getNumArgs());
+    if (CallE) return CallE->getArg(i)->getSourceRange();
+    return Msg.getArgSourceRange(i);
+  }
+};
+
+}
+}
+
+#endif

Modified: cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/TransferFuncs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/TransferFuncs.h?rev=124159&r1=124158&r2=124159&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/TransferFuncs.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/TransferFuncs.h Mon Jan 24 18:03:53 2011
@@ -17,6 +17,7 @@
 
 #include "clang/StaticAnalyzer/PathSensitive/GRState.h"
 #include "clang/StaticAnalyzer/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/PathSensitive/ObjCMessage.h"
 #include <vector>
 
 namespace clang {
@@ -47,12 +48,12 @@
                         const CallExpr* CE, SVal L,
                         ExplodedNode* Pred) {}
 
-  virtual void evalObjCMessageExpr(ExplodedNodeSet& Dst,
-                                   ExprEngine& Engine,
-                                   StmtNodeBuilder& Builder,
-                                   const ObjCMessageExpr* ME,
-                                   ExplodedNode* Pred,
-                                   const GRState *state) {}
+  virtual void evalObjCMessage(ExplodedNodeSet& Dst,
+                               ExprEngine& Engine,
+                               StmtNodeBuilder& Builder,
+                               ObjCMessage msg,
+                               ExplodedNode* Pred,
+                               const GRState *state) {}
 
   // Stores.
 

Modified: cfe/trunk/lib/StaticAnalyzer/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/CFRefCount.cpp?rev=124159&r1=124158&r2=124159&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/CFRefCount.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/CFRefCount.cpp Mon Jan 24 18:03:53 2011
@@ -40,14 +40,15 @@
 
 namespace {
 class InstanceReceiver {
-  const ObjCMessageExpr *ME;
+  ObjCMessage Msg;
   const LocationContext *LC;
 public:
-  InstanceReceiver(const ObjCMessageExpr *me = 0,
-                   const LocationContext *lc = 0) : ME(me), LC(lc) {}
+  InstanceReceiver() : LC(0) { }
+  InstanceReceiver(const ObjCMessage &msg,
+                   const LocationContext *lc = 0) : Msg(msg), LC(lc) {}
 
   bool isValid() const {
-    return ME && ME->isInstanceMessage();
+    return Msg.isValid() && Msg.isInstanceMessage();
   }
   operator bool() const {
     return isValid();
@@ -57,7 +58,7 @@
     assert(isValid());
     // We have an expression for the receiver?  Fetch the value
     // of that expression.
-    if (const Expr *Ex = ME->getInstanceReceiver())
+    if (const Expr *Ex = Msg.getInstanceReceiver())
       return state->getSValAsScalarOrLoc(Ex);
 
     // Otherwise we are sending a message to super.  In this case the
@@ -70,11 +71,11 @@
 
   SourceRange getSourceRange() const {
     assert(isValid());
-    if (const Expr *Ex = ME->getInstanceReceiver())
+    if (const Expr *Ex = Msg.getInstanceReceiver())
       return Ex->getSourceRange();
 
     // Otherwise we are sending a message to super.
-    SourceLocation L = ME->getSuperLoc();
+    SourceLocation L = Msg.getSuperLoc();
     assert(L.isValid());
     return SourceRange(L, L);
   }
@@ -798,14 +799,14 @@
 
   RetainSummary* getSummary(const FunctionDecl* FD);
 
-  RetainSummary *getInstanceMethodSummary(const ObjCMessageExpr *ME,
+  RetainSummary *getInstanceMethodSummary(const ObjCMessage &msg,
                                           const GRState *state,
                                           const LocationContext *LC);
 
-  RetainSummary* getInstanceMethodSummary(const ObjCMessageExpr* ME,
+  RetainSummary* getInstanceMethodSummary(const ObjCMessage &msg,
                                           const ObjCInterfaceDecl* ID) {
-    return getInstanceMethodSummary(ME->getSelector(), 0,
-                            ID, ME->getMethodDecl(), ME->getType());
+    return getInstanceMethodSummary(msg.getSelector(), 0,
+                            ID, msg.getMethodDecl(), msg.getType(Ctx));
   }
 
   RetainSummary* getInstanceMethodSummary(Selector S, IdentifierInfo *ClsName,
@@ -818,23 +819,15 @@
                                        const ObjCMethodDecl *MD,
                                        QualType RetTy);
 
-  RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME) {
-    ObjCInterfaceDecl *Class = 0;
-    switch (ME->getReceiverKind()) {
-    case ObjCMessageExpr::Class:
-    case ObjCMessageExpr::SuperClass:
-      Class = ME->getReceiverInterface();
-      break;
-
-    case ObjCMessageExpr::Instance:
-    case ObjCMessageExpr::SuperInstance:
-      break;
-    }
+  RetainSummary *getClassMethodSummary(const ObjCMessage &msg) {
+    const ObjCInterfaceDecl *Class = 0;
+    if (!msg.isInstanceMessage())
+      Class = msg.getReceiverInterface();
 
-    return getClassMethodSummary(ME->getSelector(),
+    return getClassMethodSummary(msg.getSelector(),
                                  Class? Class->getIdentifier() : 0,
                                  Class,
-                                 ME->getMethodDecl(), ME->getType());
+                                 msg.getMethodDecl(), msg.getType(Ctx));
   }
 
   /// getMethodSummary - This version of getMethodSummary is used to query
@@ -1310,13 +1303,13 @@
 }
 
 RetainSummary*
-RetainSummaryManager::getInstanceMethodSummary(const ObjCMessageExpr *ME,
+RetainSummaryManager::getInstanceMethodSummary(const ObjCMessage &msg,
                                                const GRState *state,
                                                const LocationContext *LC) {
 
   // We need the type-information of the tracked receiver object
   // Retrieve it from the state.
-  const Expr *Receiver = ME->getInstanceReceiver();
+  const Expr *Receiver = msg.getInstanceReceiver();
   const ObjCInterfaceDecl* ID = 0;
 
   // FIXME: Is this really working as expected?  There are cases where
@@ -1344,12 +1337,12 @@
     }
   } else {
     // FIXME: Hack for 'super'.
-    ID = ME->getReceiverInterface();
+    ID = msg.getReceiverInterface();
   }
 
   // FIXME: The receiver could be a reference to a class, meaning that
   //  we should use the class method.
-  RetainSummary *Summ = getInstanceMethodSummary(ME, ID);
+  RetainSummary *Summ = getInstanceMethodSummary(msg, ID);
 
   // Special-case: are we sending a mesage to "self"?
   //  This is a hack.  When we have full-IP this should be removed.
@@ -1693,10 +1686,10 @@
                    ExprEngine& Eng,
                    StmtNodeBuilder& Builder,
                    const Expr* Ex,
+                   const CallOrObjCMessage &callOrMsg,
                    InstanceReceiver Receiver,
                    const RetainSummary& Summ,
                    const MemRegion *Callee,
-                   ConstExprIterator arg_beg, ConstExprIterator arg_end,
                    ExplodedNode* Pred, const GRState *state);
 
   virtual void evalCall(ExplodedNodeSet& Dst,
@@ -1706,12 +1699,12 @@
                         ExplodedNode* Pred);
 
 
-  virtual void evalObjCMessageExpr(ExplodedNodeSet& Dst,
-                                   ExprEngine& Engine,
-                                   StmtNodeBuilder& Builder,
-                                   const ObjCMessageExpr* ME,
-                                   ExplodedNode* Pred,
-                                   const GRState *state);
+  virtual void evalObjCMessage(ExplodedNodeSet& Dst,
+                               ExprEngine& Engine,
+                               StmtNodeBuilder& Builder,
+                               ObjCMessage msg,
+                               ExplodedNode* Pred,
+                               const GRState *state);
   // Stores.
   virtual void evalBind(StmtNodeBuilderRef& B, SVal location, SVal val);
 
@@ -2477,16 +2470,14 @@
                              ExprEngine& Eng,
                              StmtNodeBuilder& Builder,
                              const Expr* Ex,
+                             const CallOrObjCMessage &callOrMsg,
                              InstanceReceiver Receiver,
                              const RetainSummary& Summ,
                              const MemRegion *Callee,
-                             ConstExprIterator arg_beg, 
-                             ConstExprIterator arg_end,
                              ExplodedNode* Pred, const GRState *state) {
 
   // Evaluate the effect of the arguments.
   RefVal::Kind hasErr = (RefVal::Kind) 0;
-  unsigned idx = 0;
   SourceRange ErrorRange;
   SymbolRef ErrorSym = 0;
 
@@ -2498,8 +2489,8 @@
   //  done an invalidation pass.
   llvm::DenseSet<SymbolRef> WhitelistedSymbols;
 
-  for (ConstExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
-    SVal V = state->getSValAsScalarOrLoc(*I);
+  for (unsigned idx = 0, e = callOrMsg.getNumArgs(); idx != e; ++idx) {
+    SVal V = callOrMsg.getArgSValAsScalarOrLoc(idx);
     SymbolRef Sym = V.getAsLocSymbol();
 
     if (Sym)
@@ -2507,7 +2498,7 @@
         WhitelistedSymbols.insert(Sym);
         state = Update(state, Sym, *T, Summ.getArg(idx), hasErr);
         if (hasErr) {
-          ErrorRange = (*I)->getSourceRange();
+          ErrorRange = callOrMsg.getArgSourceRange(idx);
           ErrorSym = Sym;
           break;
         }
@@ -2650,19 +2641,7 @@
       // FIXME: We eventually should handle structs and other compound types
       // that are returned by value.
 
-      QualType T = Ex->getType();
-
-      // For CallExpr, use the result type to know if it returns a reference.
-      if (const CallExpr *CE = dyn_cast<CallExpr>(Ex)) {
-        const Expr *Callee = CE->getCallee();
-        if (const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl())
-          T = FD->getResultType();
-      }
-      else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(Ex)) {
-        if (const ObjCMethodDecl *MD = ME->getMethodDecl())
-          T = MD->getResultType();
-      }
-
+      QualType T = callOrMsg.getResultType(Eng.getContext());
       if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
         unsigned Count = Builder.getCurrentBlockCount();
         SValBuilder &svalBuilder = Eng.getSValBuilder();
@@ -2675,9 +2654,8 @@
 
     case RetEffect::Alias: {
       unsigned idx = RE.getIndex();
-      assert (arg_end >= arg_beg);
-      assert (idx < (unsigned) (arg_end - arg_beg));
-      SVal V = state->getSValAsScalarOrLoc(*(arg_beg+idx));
+      assert (idx < callOrMsg.getNumArgs());
+      SVal V = callOrMsg.getArgSValAsScalarOrLoc(idx);
       state = state->BindExpr(Ex, V, false);
       break;
     }
@@ -2756,25 +2734,28 @@
   }
 
   assert(Summ);
-  evalSummary(Dst, Eng, Builder, CE, 0, *Summ, L.getAsRegion(),
-              CE->arg_begin(), CE->arg_end(), Pred, Builder.GetState(Pred));
+  evalSummary(Dst, Eng, Builder, CE,
+              CallOrObjCMessage(CE, Builder.GetState(Pred)),
+              InstanceReceiver(), *Summ,L.getAsRegion(),
+              Pred, Builder.GetState(Pred));
 }
 
-void CFRefCount::evalObjCMessageExpr(ExplodedNodeSet& Dst,
-                                     ExprEngine& Eng,
-                                     StmtNodeBuilder& Builder,
-                                     const ObjCMessageExpr* ME,
-                                     ExplodedNode* Pred,
-                                     const GRState *state) {
+void CFRefCount::evalObjCMessage(ExplodedNodeSet& Dst,
+                                 ExprEngine& Eng,
+                                 StmtNodeBuilder& Builder,
+                                 ObjCMessage msg,
+                                 ExplodedNode* Pred,
+                                 const GRState *state) {
   RetainSummary *Summ =
-    ME->isInstanceMessage()
-      ? Summaries.getInstanceMethodSummary(ME, state,Pred->getLocationContext())
-      : Summaries.getClassMethodSummary(ME);
+    msg.isInstanceMessage()
+      ? Summaries.getInstanceMethodSummary(msg, state,Pred->getLocationContext())
+      : Summaries.getClassMethodSummary(msg);
 
   assert(Summ && "RetainSummary is null");
-  evalSummary(Dst, Eng, Builder, ME,
-              InstanceReceiver(ME, Pred->getLocationContext()), *Summ, NULL,
-              ME->arg_begin(), ME->arg_end(), Pred, state);
+  evalSummary(Dst, Eng, Builder, msg.getOriginExpr(),
+              CallOrObjCMessage(msg, Builder.GetState(Pred)),
+              InstanceReceiver(msg, Pred->getLocationContext()), *Summ, NULL,
+              Pred, state);
 }
 
 namespace {

Modified: cfe/trunk/lib/StaticAnalyzer/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/CMakeLists.txt?rev=124159&r1=124158&r2=124159&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/CMakeLists.txt (original)
+++ cfe/trunk/lib/StaticAnalyzer/CMakeLists.txt Mon Jan 24 18:03:53 2011
@@ -24,6 +24,7 @@
   HTMLDiagnostics.cpp
   ManagerRegistry.cpp
   MemRegion.cpp
+  ObjCMessage.cpp
   PathDiagnostic.cpp
   PlistDiagnostics.cpp
   RangeConstraintManager.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp?rev=124159&r1=124158&r2=124159&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp Mon Jan 24 18:03:53 2011
@@ -42,14 +42,14 @@
 // Utility functions.
 //===----------------------------------------------------------------------===//
 
-static const ObjCInterfaceType* GetReceiverType(const ObjCMessageExpr* ME) {
-  if (ObjCInterfaceDecl *ID = ME->getReceiverInterface())
+static const ObjCInterfaceType* GetReceiverType(const ObjCMessage &msg) {
+  if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface())
     return ID->getTypeForDecl()->getAs<ObjCInterfaceType>();
   return NULL;
 }
 
-static const char* GetReceiverNameType(const ObjCMessageExpr* ME) {
-  if (const ObjCInterfaceType *ReceiverType = GetReceiverType(ME))
+static const char* GetReceiverNameType(const ObjCMessage &msg) {
+  if (const ObjCInterfaceType *ReceiverType = GetReceiverType(msg))
     return ReceiverType->getDecl()->getIdentifier()->getNameStart();
   return NULL;
 }
@@ -69,16 +69,16 @@
 namespace {
   class NilArgChecker : public CheckerVisitor<NilArgChecker> {
     APIMisuse *BT;
-    void WarnNilArg(CheckerContext &C, const ObjCMessageExpr* ME, unsigned Arg);
+    void WarnNilArg(CheckerContext &C, const ObjCMessage &msg, unsigned Arg);
   public:
     NilArgChecker() : BT(0) {}
     static void *getTag() { static int x = 0; return &x; }
-    void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
+    void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
   };
 }
 
 void NilArgChecker::WarnNilArg(CheckerContext &C,
-                               const clang::ObjCMessageExpr *ME,
+                               const ObjCMessage &msg,
                                unsigned int Arg)
 {
   if (!BT)
@@ -87,24 +87,24 @@
   if (ExplodedNode *N = C.generateSink()) {
     llvm::SmallString<128> sbuf;
     llvm::raw_svector_ostream os(sbuf);
-    os << "Argument to '" << GetReceiverNameType(ME) << "' method '"
-       << ME->getSelector().getAsString() << "' cannot be nil";
+    os << "Argument to '" << GetReceiverNameType(msg) << "' method '"
+       << msg.getSelector().getAsString() << "' cannot be nil";
 
     RangedBugReport *R = new RangedBugReport(*BT, os.str(), N);
-    R->addRange(ME->getArg(Arg)->getSourceRange());
+    R->addRange(msg.getArgSourceRange(Arg));
     C.EmitReport(R);
   }
 }
 
-void NilArgChecker::PreVisitObjCMessageExpr(CheckerContext &C,
-                                            const ObjCMessageExpr *ME)
+void NilArgChecker::preVisitObjCMessage(CheckerContext &C,
+                                        ObjCMessage msg)
 {
-  const ObjCInterfaceType *ReceiverType = GetReceiverType(ME);
+  const ObjCInterfaceType *ReceiverType = GetReceiverType(msg);
   if (!ReceiverType)
     return;
   
   if (isNSString(ReceiverType->getDecl()->getIdentifier()->getName())) {
-    Selector S = ME->getSelector();
+    Selector S = msg.getSelector();
     
     if (S.isUnarySelector())
       return;
@@ -127,8 +127,8 @@
         Name == "compare:options:range:locale:" ||
         Name == "componentsSeparatedByCharactersInSet:" ||
         Name == "initWithFormat:") {
-      if (isNil(C.getState()->getSVal(ME->getArg(0))))
-        WarnNilArg(C, ME, 0);
+      if (isNil(msg.getArgSVal(0, C.getState())))
+        WarnNilArg(C, msg, 0);
     }
   }
 }
@@ -441,12 +441,12 @@
 
   static void *getTag() { static int x = 0; return &x; }
       
-  void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);    
+  void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
 };
 }
 
-void ClassReleaseChecker::PreVisitObjCMessageExpr(CheckerContext &C,
-                                                  const ObjCMessageExpr *ME) {
+void ClassReleaseChecker::preVisitObjCMessage(CheckerContext &C,
+                                              ObjCMessage msg) {
   
   if (!BT) {
     BT = new APIMisuse("message incorrectly sent to class instead of class "
@@ -459,21 +459,12 @@
     drainS = GetNullarySelector("drain", Ctx);
   }
   
-  ObjCInterfaceDecl *Class = 0;
-
-  switch (ME->getReceiverKind()) {
-  case ObjCMessageExpr::Class:
-    Class = ME->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
-    break;
-  case ObjCMessageExpr::SuperClass:
-    Class = ME->getSuperType()->getAs<ObjCObjectType>()->getInterface();
-    break;
-  case ObjCMessageExpr::Instance:
-  case ObjCMessageExpr::SuperInstance:
+  if (msg.isInstanceMessage())
     return;
-  }
+  const ObjCInterfaceDecl *Class = msg.getReceiverInterface();
+  assert(Class);
 
-  Selector S = ME->getSelector();
+  Selector S = msg.getSelector();
   if (!(S == releaseS || S == retainS || S == autoreleaseS || S == drainS))
     return;
   
@@ -486,7 +477,7 @@
        << "' and not the class directly";
   
     RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
-    report->addRange(ME->getSourceRange());
+    report->addRange(msg.getSourceRange());
     C.EmitReport(report);
   }
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp?rev=124159&r1=124158&r2=124159&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp Mon Jan 24 18:03:53 2011
@@ -41,19 +41,21 @@
   }
 
   void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
-  void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);
-  bool evalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME);
+  void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
+  bool evalNilReceiver(CheckerContext &C, ObjCMessage msg);
 
 private:
-  bool PreVisitProcessArg(CheckerContext &C, const Expr *Ex,
-                          const char *BT_desc, BugType *&BT);
+  void PreVisitProcessArgs(CheckerContext &C, CallOrObjCMessage callOrMsg,
+                           const char *BT_desc, BugType *&BT);
+  bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange argRange,
+                          const Expr *argEx, const char *BT_desc, BugType *&BT);
 
   void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE);
-  void emitNilReceiverBug(CheckerContext &C, const ObjCMessageExpr *ME,
+  void emitNilReceiverBug(CheckerContext &C, const ObjCMessage &msg,
                           ExplodedNode *N);
 
   void HandleNilReceiver(CheckerContext &C, const GRState *state,
-                         const ObjCMessageExpr *ME);
+                         ObjCMessage msg);
 
   void LazyInit_BT(const char *desc, BugType *&BT) {
     if (!BT)
@@ -78,21 +80,32 @@
   C.EmitReport(R);
 }
 
+void CallAndMessageChecker::PreVisitProcessArgs(CheckerContext &C,
+                                                CallOrObjCMessage callOrMsg,
+                                                const char *BT_desc,
+                                                BugType *&BT) {
+  for (unsigned i = 0, e = callOrMsg.getNumArgs(); i != e; ++i)
+    if (PreVisitProcessArg(C, callOrMsg.getArgSVal(i),
+                           callOrMsg.getArgSourceRange(i), callOrMsg.getArg(i),
+                           BT_desc, BT))
+      return;
+}
+
 bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
-                                               const Expr *Ex,
+                                               SVal V, SourceRange argRange,
+                                               const Expr *argEx,
                                                const char *BT_desc,
                                                BugType *&BT) {
 
-  const SVal &V = C.getState()->getSVal(Ex);
-
   if (V.isUndef()) {
     if (ExplodedNode *N = C.generateSink()) {
       LazyInit_BT(BT_desc, BT);
 
       // Generate a report for this bug.
       EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N);
-      R->addRange(Ex->getSourceRange());
-      R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
+      R->addRange(argRange);
+      if (argEx)
+        R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, argEx);
       C.EmitReport(R);
     }
     return true;
@@ -172,7 +185,7 @@
 
         // Generate a report for this bug.
         EnhancedBugReport *R = new EnhancedBugReport(*BT, os.str(), N);
-        R->addRange(Ex->getSourceRange());
+        R->addRange(argRange);
 
         // FIXME: enhance track back for uninitialized value for arbitrary
         // memregions
@@ -206,21 +219,18 @@
     EmitBadCall(BT_call_null, C, CE);
   }
 
-  for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
-       I != E; ++I)
-    if (PreVisitProcessArg(C, *I,
-                           "Function call argument is an uninitialized value",
-                           BT_call_arg))
-      return;
+  PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState()),
+                      "Function call argument is an uninitialized value",
+                      BT_call_arg);
 }
 
-void CallAndMessageChecker::PreVisitObjCMessageExpr(CheckerContext &C,
-                                                    const ObjCMessageExpr *ME) {
+void CallAndMessageChecker::preVisitObjCMessage(CheckerContext &C,
+                                                ObjCMessage msg) {
 
   const GRState *state = C.getState();
 
   // FIXME: Handle 'super'?
-  if (const Expr *receiver = ME->getInstanceReceiver())
+  if (const Expr *receiver = msg.getInstanceReceiver())
     if (state->getSVal(receiver).isUndef()) {
       if (ExplodedNode *N = C.generateSink()) {
         if (!BT_msg_undef)
@@ -237,22 +247,19 @@
     }
 
   // Check for any arguments that are uninitialized/undefined.
-  for (ObjCMessageExpr::const_arg_iterator I = ME->arg_begin(),
-         E = ME->arg_end(); I != E; ++I)
-    if (PreVisitProcessArg(C, *I,
-                           "Argument in message expression "
-                           "is an uninitialized value", BT_msg_arg))
-        return;
+  PreVisitProcessArgs(C, CallOrObjCMessage(msg, state),
+                      "Argument in message expression "
+                      "is an uninitialized value", BT_msg_arg);
 }
 
 bool CallAndMessageChecker::evalNilReceiver(CheckerContext &C,
-                                            const ObjCMessageExpr *ME) {
-  HandleNilReceiver(C, C.getState(), ME);
+                                            ObjCMessage msg) {
+  HandleNilReceiver(C, C.getState(), msg);
   return true; // Nil receiver is not handled elsewhere.
 }
 
 void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
-                                               const ObjCMessageExpr *ME,
+                                               const ObjCMessage &msg,
                                                ExplodedNode *N) {
 
   if (!BT_msg_ret)
@@ -262,12 +269,12 @@
 
   llvm::SmallString<200> buf;
   llvm::raw_svector_ostream os(buf);
-  os << "The receiver of message '" << ME->getSelector().getAsString()
+  os << "The receiver of message '" << msg.getSelector().getAsString()
      << "' is nil and returns a value of type '"
-     << ME->getType().getAsString() << "' that will be garbage";
+     << msg.getType(C.getASTContext()).getAsString() << "' that will be garbage";
 
   EnhancedBugReport *report = new EnhancedBugReport(*BT_msg_ret, os.str(), N);
-  if (const Expr *receiver = ME->getInstanceReceiver()) {
+  if (const Expr *receiver = msg.getInstanceReceiver()) {
     report->addRange(receiver->getSourceRange());
     report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue,
                               receiver);
@@ -284,22 +291,22 @@
 
 void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
                                               const GRState *state,
-                                              const ObjCMessageExpr *ME) {
+                                              ObjCMessage msg) {
+  ASTContext &Ctx = C.getASTContext();
 
   // Check the return type of the message expression.  A message to nil will
   // return different values depending on the return type and the architecture.
-  QualType RetTy = ME->getType();
+  QualType RetTy = msg.getType(Ctx);
 
-  ASTContext &Ctx = C.getASTContext();
   CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
 
   if (CanRetTy->isStructureOrClassType()) {
     // FIXME: At some point we shouldn't rely on isConsumedExpr(), but instead
     // have the "use of undefined value" be smarter about where the
     // undefined value came from.
-    if (C.getPredecessor()->getParentMap().isConsumedExpr(ME)) {
+    if (C.getPredecessor()->getParentMap().isConsumedExpr(msg.getOriginExpr())){
       if (ExplodedNode* N = C.generateSink(state))
-        emitNilReceiverBug(C, ME, N);
+        emitNilReceiverBug(C, msg, N);
       return;
     }
 
@@ -311,7 +318,7 @@
 
   // Other cases: check if the return type is smaller than void*.
   if (CanRetTy != Ctx.VoidTy &&
-      C.getPredecessor()->getParentMap().isConsumedExpr(ME)) {
+      C.getPredecessor()->getParentMap().isConsumedExpr(msg.getOriginExpr())) {
     // Compute: sizeof(void *) and sizeof(return type)
     const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
     const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);
@@ -324,7 +331,7 @@
            Ctx.LongLongTy == CanRetTy ||
            Ctx.UnsignedLongLongTy == CanRetTy))) {
       if (ExplodedNode* N = C.generateSink(state))
-        emitNilReceiverBug(C, ME, N);
+        emitNilReceiverBug(C, msg, N);
       return;
     }
 
@@ -341,8 +348,8 @@
     // it most likely isn't nil.  We should assume the semantics
     // of this case unless we have *a lot* more knowledge.
     //
-    SVal V = C.getSValBuilder().makeZeroVal(ME->getType());
-    C.generateNode(state->BindExpr(ME, V));
+    SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx));
+    C.generateNode(state->BindExpr(msg.getOriginExpr(), V));
     return;
   }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp?rev=124159&r1=124158&r2=124159&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp Mon Jan 24 18:03:53 2011
@@ -145,10 +145,49 @@
   // automatically.
 }
 
-void ExprEngine::CheckerEvalNilReceiver(const ObjCMessageExpr *ME,
-                                          ExplodedNodeSet &Dst,
-                                          const GRState *state,
-                                          ExplodedNode *Pred) {
+void ExprEngine::CheckerVisitObjCMessage(const ObjCMessage &msg,
+                                         ExplodedNodeSet &Dst,
+                                         ExplodedNodeSet &Src,
+                                         bool isPrevisit) {
+
+  if (Checkers.empty()) {
+    Dst.insert(Src);
+    return;
+  }
+
+  ExplodedNodeSet Tmp;
+  ExplodedNodeSet *PrevSet = &Src;
+
+  for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
+  {
+    ExplodedNodeSet *CurrSet = 0;
+    if (I+1 == E)
+      CurrSet = &Dst;
+    else {
+      CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
+      CurrSet->clear();
+    }
+
+    void *tag = I->first;
+    Checker *checker = I->second;
+
+    for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
+         NI != NE; ++NI)
+      checker->GR_visitObjCMessage(*CurrSet, *Builder, *this, msg,
+                                   *NI, tag, isPrevisit);
+
+    // Update which NodeSet is the current one.
+    PrevSet = CurrSet;
+  }
+
+  // Don't autotransition.  The CheckerContext objects should do this
+  // automatically.
+}
+
+void ExprEngine::CheckerEvalNilReceiver(const ObjCMessage &msg,
+                                        ExplodedNodeSet &Dst,
+                                        const GRState *state,
+                                        ExplodedNode *Pred) {
   bool evaluated = false;
   ExplodedNodeSet DstTmp;
 
@@ -156,7 +195,7 @@
     void *tag = I->first;
     Checker *checker = I->second;
 
-    if (checker->GR_evalNilReceiver(DstTmp, *Builder, *this, ME, Pred, state,
+    if (checker->GR_evalNilReceiver(DstTmp, *Builder, *this, msg, Pred, state,
                                     tag)) {
       evaluated = true;
       break;
@@ -2263,7 +2302,7 @@
 
   // Now that the arguments are processed, handle the previsits checks.
   ExplodedNodeSet DstPrevisit;
-  CheckerVisit(ME, DstPrevisit, ArgsEvaluated, PreVisitStmtCallback);
+  CheckerVisitObjCMessage(ME, DstPrevisit, ArgsEvaluated, /*isPreVisit=*/true);
 
   // Proceed with evaluate the message expression.
   ExplodedNodeSet dstEval;
@@ -2305,7 +2344,7 @@
         Builder->BuildSinks = true;
 
       // Dispatch to plug-in transfer function.
-      evalObjCMessageExpr(dstEval, ME, Pred, notNilState);
+      evalObjCMessage(dstEval, ME, Pred, notNilState);
     }
     else if (ObjCInterfaceDecl *Iface = ME->getReceiverInterface()) {
       IdentifierInfo* ClsName = Iface->getIdentifier();
@@ -2353,7 +2392,7 @@
         Builder->BuildSinks = true;
 
       // Dispatch to plug-in transfer function.
-      evalObjCMessageExpr(dstEval, ME, Pred, Builder->GetState(Pred));
+      evalObjCMessage(dstEval, ME, Pred, Builder->GetState(Pred));
     }
 
     // Handle the case where no nodes where generated.  Auto-generate that
@@ -2365,7 +2404,7 @@
 
   // Finally, perform the post-condition check of the ObjCMessageExpr and store
   // the created nodes in 'Dst'.
-  CheckerVisit(ME, Dst, dstEval, PostVisitStmtCallback);
+  CheckerVisitObjCMessage(ME, Dst, dstEval, /*isPreVisit=*/false);
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp?rev=124159&r1=124158&r2=124159&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp Mon Jan 24 18:03:53 2011
@@ -39,7 +39,7 @@
     return &x;
   }
 
-  void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME);    
+  void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg);    
 };
 
 } // end anonymous namespace
@@ -54,10 +54,10 @@
 }
 
 void
-NSAutoreleasePoolChecker::PreVisitObjCMessageExpr(CheckerContext &C,
-                                                  const ObjCMessageExpr *ME) {
+NSAutoreleasePoolChecker::preVisitObjCMessage(CheckerContext &C,
+                                              ObjCMessage msg) {
   
-  const Expr *receiver = ME->getInstanceReceiver();
+  const Expr *receiver = msg.getInstanceReceiver();
   if (!receiver)
     return;
   
@@ -75,13 +75,13 @@
     return;
   
   // Sending 'release' message?
-  if (ME->getSelector() != releaseS)
+  if (msg.getSelector() != releaseS)
     return;
                      
-  SourceRange R = ME->getSourceRange();
+  SourceRange R = msg.getSourceRange();
 
   C.getBugReporter().EmitBasicReport("Use -drain instead of -release",
     "API Upgrade (Apple)",
     "Use -drain instead of -release when using NSAutoreleasePool "
-    "and garbage collection", ME->getLocStart(), &R, 1);
+    "and garbage collection", R.getBegin(), &R, 1);
 }

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp?rev=124159&r1=124158&r2=124159&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp Mon Jan 24 18:03:53 2011
@@ -58,7 +58,7 @@
 
 static bool shouldRunOnFunctionOrMethod(const NamedDecl *ND);
 static bool isInitializationMethod(const ObjCMethodDecl *MD);
-static bool isInitMessage(const ObjCMessageExpr *E);
+static bool isInitMessage(const ObjCMessage &msg);
 static bool isSelfVar(SVal location, CheckerContext &C);
 
 namespace {
@@ -82,7 +82,7 @@
 
 public:
   static void *getTag() { static int tag = 0; return &tag; }
-  void PostVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *E);
+  void postVisitObjCMessage(CheckerContext &C, ObjCMessage msg);
   void PostVisitObjCIvarRefExpr(CheckerContext &C, const ObjCIvarRefExpr *E);
   void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *S);
   void PreVisitGenericCall(CheckerContext &C, const CallExpr *CE);
@@ -176,8 +176,8 @@
   C.EmitReport(report);
 }
 
-void ObjCSelfInitChecker::PostVisitObjCMessageExpr(CheckerContext &C,
-                                                   const ObjCMessageExpr *E) {
+void ObjCSelfInitChecker::postVisitObjCMessage(CheckerContext &C,
+                                               ObjCMessage msg) {
   // When encountering a message that does initialization (init rule),
   // tag the return value so that we know later on that if self has this value
   // then it is properly initialized.
@@ -187,10 +187,10 @@
                                      C.getCurrentAnalysisContext()->getDecl())))
     return;
 
-  if (isInitMessage(E)) {
+  if (isInitMessage(msg)) {
     // Tag the return value as the result of an initializer.
     const GRState *state = C.getState();
-    SVal V = state->getSVal(E);
+    SVal V = state->getSVal(msg.getOriginExpr());
     addSelfFlag(V, SelfFlag_InitRes, C);
     return;
   }
@@ -301,6 +301,6 @@
                                     /*ignorePrefix=*/false) == cocoa::InitRule;
 }
 
-static bool isInitMessage(const ObjCMessageExpr *E) {
-  return cocoa::deriveNamingConvention(E->getSelector()) == cocoa::InitRule;
+static bool isInitMessage(const ObjCMessage &msg) {
+  return cocoa::deriveNamingConvention(msg.getSelector()) == cocoa::InitRule;
 }

Added: cfe/trunk/lib/StaticAnalyzer/ObjCMessage.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/ObjCMessage.cpp?rev=124159&view=auto
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/ObjCMessage.cpp (added)
+++ cfe/trunk/lib/StaticAnalyzer/ObjCMessage.cpp Mon Jan 24 18:03:53 2011
@@ -0,0 +1,99 @@
+//===- ObjCMessage.cpp - Wrapper for ObjC messages and dot syntax -*- C++ -*--//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ObjCMessage which serves as a common wrapper for ObjC
+// message expressions or implicit messages for loading/storing ObjC properties.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/PathSensitive/ObjCMessage.h"
+
+using namespace clang;
+using namespace ento;
+
+QualType ObjCMessage::getType(ASTContext &ctx) const {
+  assert(isValid() && "This ObjCMessage is uninitialized!");
+  if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+    return msgE->getType();
+  const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+  if (isPropertySetter())
+    return ctx.VoidTy;
+  return propE->getType();
+}
+
+Selector ObjCMessage::getSelector() const {
+  assert(isValid() && "This ObjCMessage is uninitialized!");
+  if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+    return msgE->getSelector();
+  const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+  if (isPropertySetter())
+    return propE->getSetterSelector();
+  return propE->getGetterSelector();
+}
+
+const ObjCMethodDecl *ObjCMessage::getMethodDecl() const {
+  assert(isValid() && "This ObjCMessage is uninitialized!");
+  if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+    return msgE->getMethodDecl();
+  const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+  if (propE->isImplicitProperty())
+    return isPropertySetter() ? propE->getImplicitPropertySetter()
+                              : propE->getImplicitPropertyGetter();
+  return 0;
+}
+
+const ObjCInterfaceDecl *ObjCMessage::getReceiverInterface() const {
+  assert(isValid() && "This ObjCMessage is uninitialized!");
+  if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+    return msgE->getReceiverInterface();
+  const ObjCPropertyRefExpr *propE = cast<ObjCPropertyRefExpr>(MsgOrPropE);
+  if (propE->isClassReceiver())
+    return propE->getClassReceiver();
+  QualType recT;
+  if (const Expr *recE = getInstanceReceiver())
+    recT = recE->getType();
+  else {
+    assert(propE->isSuperReceiver());
+    recT = propE->getSuperReceiverType();
+  }
+  if (const ObjCObjectPointerType *Ptr = recT->getAs<ObjCObjectPointerType>())
+    return Ptr->getInterfaceDecl();
+  return 0;
+}
+
+const Expr *ObjCMessage::getArgExpr(unsigned i) const {
+  assert(isValid() && "This ObjCMessage is uninitialized!");
+  assert(i < getNumArgs() && "Invalid index for argument");
+  if (const ObjCMessageExpr *msgE = dyn_cast<ObjCMessageExpr>(MsgOrPropE))
+    return msgE->getArg(i);
+  assert(isPropertySetter());
+  if (const BinaryOperator *bop = dyn_cast<BinaryOperator>(OriginE))
+    if (bop->isAssignmentOp())
+      return bop->getRHS();
+  return 0;
+}
+
+QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const {
+  if (CallE) {
+    const Expr *Callee = CallE->getCallee();
+    if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl())
+      return FD->getResultType();
+    return CallE->getType();
+  }
+  return Msg.getResultType(ctx);
+}
+
+SVal CallOrObjCMessage::getArgSValAsScalarOrLoc(unsigned i) const {
+  assert(i < getNumArgs());
+  if (CallE) return State->getSValAsScalarOrLoc(CallE->getArg(i));
+  QualType argT = Msg.getArgType(i);
+  if (Loc::IsLocType(argT) || argT->isIntegerType())
+    return Msg.getArgSVal(i, State);
+  return UnknownVal();
+}





More information about the cfe-commits mailing list