[cfe-commits] r160022 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h include/clang/StaticAnalyzer/Core/PathSensitive/Store.h lib/StaticAnalyzer/Core/Calls.cpp lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp lib/StaticAnalyzer/Core/ProgramState.cpp lib/StaticAnalyzer/Core/RegionStore.cpp lib/StaticAnalyzer/Core/Store.cpp test/Analysis/operator-calls.cpp

Jordan Rose jordan_rose at apple.com
Tue Jul 10 15:07:58 PDT 2012


Author: jrose
Date: Tue Jul 10 17:07:57 2012
New Revision: 160022

URL: http://llvm.org/viewvc/llvm-project?rev=160022&view=rev
Log:
[analyzer] Use CallEvent for building inlined stack frames.

In order to accomplish this, we now build the callee's stack frame
as part of the CallEnter node, rather than the subsequent BlockEdge node.
This should not have any effect on perceived behavior or diagnostics.

This makes it safe to re-enable inlining of member overloaded operators.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
    cfe/trunk/lib/StaticAnalyzer/Core/Calls.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
    cfe/trunk/test/Analysis/operator-calls.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=160022&r1=160021&r2=160022&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Calls.h Tue Jul 10 17:07:57 2012
@@ -73,10 +73,6 @@
   /// result of this call.
   virtual void addExtraInvalidatedRegions(RegionList &Regions) const {}
 
-  typedef const ParmVarDecl * const *param_iterator;
-  virtual param_iterator param_begin() const = 0;
-  virtual param_iterator param_end() const = 0;
-
   virtual QualType getDeclaredResultType() const { return QualType(); }
 
 public:
@@ -147,6 +143,10 @@
   /// \brief Returns the result type, adjusted for references.
   QualType getResultType() const;
 
+  /// \brief Returns the value of the implicit 'this' object, or UndefinedVal if
+  /// this is not a C++ member function call.
+  virtual SVal getCXXThisVal() const { return UndefinedVal(); }
+
   /// \brief Returns true if any of the arguments appear to represent callbacks.
   bool hasNonZeroCallbackArg() const;
 
@@ -174,18 +174,44 @@
   /// inlining.
   static bool mayBeInlined(const Stmt *S);
 
-  // Iterator access to parameter types.
+  // Iterator access to formal parameters and their types.
 private:
   typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun;
   
 public:
+  typedef const ParmVarDecl * const *param_iterator;
+
+  /// Returns an iterator over the call's formal parameters.
+  ///
+  /// If UseDefinitionParams is set, this will return the parameter decls
+  /// used in the callee's definition (suitable for inlining). Most of the
+  /// time it is better to use the decl found by name lookup, which likely
+  /// carries more annotations.
+  ///
+  /// Remember that the number of formal parameters may not match the number
+  /// of arguments for all calls. However, the first parameter will always
+  /// correspond with the argument value returned by \c getArgSVal(0).
+  ///
+  /// If the call has no accessible declaration (or definition, if
+  /// \p UseDefinitionParams is set), \c param_begin() will be equal to
+  /// \c param_end().
+  virtual param_iterator param_begin(bool UseDefinitionParams = false) const = 0;
+  /// \sa param_begin()
+  virtual param_iterator param_end(bool UseDefinitionParams = false) const = 0;
+
   typedef llvm::mapped_iterator<param_iterator, get_type_fun>
     param_type_iterator;
 
+  /// Returns an iterator over the types of the call's formal parameters.
+  ///
+  /// This uses the callee decl found by default name lookup rather than the
+  /// definition because it represents a public interface, and probably has
+  /// more annotations.
   param_type_iterator param_type_begin() const {
     return llvm::map_iterator(param_begin(),
                               get_type_fun(&ParmVarDecl::getType));
   }
+  /// \sa param_type_begin()
   param_type_iterator param_type_end() const {
     return llvm::map_iterator(param_end(), get_type_fun(&ParmVarDecl::getType));
   }
@@ -200,8 +226,8 @@
   AnyFunctionCall(ProgramStateRef St, const LocationContext *LCtx, Kind K)
     : CallEvent(St, LCtx, K) {}
 
-  param_iterator param_begin() const;
-  param_iterator param_end() const;
+  param_iterator param_begin(bool UseDefinitionParams = false) const;
+  param_iterator param_end(bool UseDefinitionParams = false) const;
 
   QualType getDeclaredResultType() const;
 
@@ -282,6 +308,8 @@
     return cast<CXXMemberCallExpr>(SimpleCall::getOriginExpr());
   }
 
+  SVal getCXXThisVal() const;
+
   static bool classof(const CallEvent *CA) {
     return CA->getKind() == CE_CXXMember;
   }
@@ -309,6 +337,8 @@
     return getOriginExpr()->getArg(Index + 1);
   }
 
+  SVal getCXXThisVal() const;
+
   static bool classof(const CallEvent *CA) {
     return CA->getKind() == CE_CXXMemberOperator;
   }
@@ -321,8 +351,8 @@
 protected:
   void addExtraInvalidatedRegions(RegionList &Regions) const;
 
-  param_iterator param_begin() const;
-  param_iterator param_end() const;
+  param_iterator param_begin(bool UseDefinitionParams = false) const;
+  param_iterator param_end(bool UseDefinitionParams = false) const;
 
   QualType getDeclaredResultType() const;
 
@@ -387,6 +417,8 @@
     return CE->getArg(Index);
   }
 
+  SVal getCXXThisVal() const;
+
   static bool classof(const CallEvent *CA) {
     return CA->getKind() == CE_CXXConstructor;
   }
@@ -417,6 +449,8 @@
   const CXXDestructorDecl *getDecl() const { return DD; }
   unsigned getNumArgs() const { return 0; }
 
+  SVal getCXXThisVal() const;
+
   static bool classof(const CallEvent *CA) {
     return CA->getKind() == CE_CXXDestructor;
   }
@@ -465,8 +499,8 @@
 
   void addExtraInvalidatedRegions(RegionList &Regions) const;
 
-  param_iterator param_begin() const;
-  param_iterator param_end() const;
+  param_iterator param_begin(bool UseDefinitionParams = false) const;
+  param_iterator param_end(bool UseDefinitionParams = false) const;
 
   QualType getDeclaredResultType() const;
 

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h?rev=160022&r1=160021&r2=160022&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h Tue Jul 10 17:07:57 2012
@@ -223,8 +223,8 @@
 
   /// enterStackFrame - Returns the state for entry to the given stack frame,
   ///  preserving the current state.
-  ProgramStateRef enterStackFrame(const LocationContext *callerCtx,
-                                      const StackFrameContext *calleeCtx) const;
+  ProgramStateRef enterStackFrame(const CallEvent &Call,
+                                  const StackFrameContext *CalleeCtx) const;
 
   /// Get the lvalue for a variable reference.
   Loc getLValue(const VarDecl *D, const LocationContext *LC) const;

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h?rev=160022&r1=160021&r2=160022&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h Tue Jul 10 17:07:57 2012
@@ -199,9 +199,9 @@
 
   /// enterStackFrame - Let the StoreManager to do something when execution
   /// engine is about to execute into a callee.
-  virtual StoreRef enterStackFrame(ProgramStateRef state,
-                                   const LocationContext *callerCtx,
-                                   const StackFrameContext *calleeCtx);
+  StoreRef enterStackFrame(Store store,
+                           const CallEvent &Call,
+                           const StackFrameContext *CalleeCtx);
 
   virtual void print(Store store, raw_ostream &Out,
                      const char* nl, const char *sep) = 0;

Modified: cfe/trunk/lib/StaticAnalyzer/Core/Calls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Calls.cpp?rev=160022&r1=160021&r2=160022&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Calls.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Calls.cpp Tue Jul 10 17:07:57 2012
@@ -219,20 +219,22 @@
 }
 
 
-CallEvent::param_iterator AnyFunctionCall::param_begin() const {
-  const FunctionDecl *D = getDecl();
+CallEvent::param_iterator
+AnyFunctionCall::param_begin(bool UseDefinitionParams) const {
+  const Decl *D = UseDefinitionParams ? getDefinition() : getDecl();
   if (!D)
     return 0;
 
-  return D->param_begin();
+  return cast<FunctionDecl>(D)->param_begin();
 }
 
-CallEvent::param_iterator AnyFunctionCall::param_end() const {
-  const FunctionDecl *D = getDecl();
+CallEvent::param_iterator
+AnyFunctionCall::param_end(bool UseDefinitionParams) const {
+  const Decl *D = UseDefinitionParams ? getDefinition() : getDecl();
   if (!D)
     return 0;
 
-  return D->param_end();
+  return cast<FunctionDecl>(D)->param_end();
 }
 
 QualType AnyFunctionCall::getDeclaredResultType() const {
@@ -309,23 +311,31 @@
 }
 
 
-void CXXMemberCall::addExtraInvalidatedRegions(RegionList &Regions) const {
+SVal CXXMemberCall::getCXXThisVal() const {
   const Expr *Base = getOriginExpr()->getImplicitObjectArgument();
 
   // FIXME: Will eventually need to cope with member pointers.  This is
   // a limitation in getImplicitObjectArgument().
   if (!Base)
-    return;
-    
-  if (const MemRegion *R = getSVal(Base).getAsRegion())
+    return UnknownVal();
+
+  return getSVal(Base);
+}
+
+void CXXMemberCall::addExtraInvalidatedRegions(RegionList &Regions) const {    
+  if (const MemRegion *R = getCXXThisVal().getAsRegion())
     Regions.push_back(R);
 }
 
 
+SVal CXXMemberOperatorCall::getCXXThisVal() const {
+  const Expr *Base = getOriginExpr()->getArg(0);
+  return getSVal(Base);
+}
+
 void
 CXXMemberOperatorCall::addExtraInvalidatedRegions(RegionList &Regions) const {
-  const Expr *Base = getOriginExpr()->getArg(0);
-  if (const MemRegion *R = getSVal(Base).getAsRegion())
+  if (const MemRegion *R = getCXXThisVal().getAsRegion())
     Regions.push_back(R);
 }
 
@@ -337,14 +347,22 @@
   return dyn_cast_or_null<BlockDataRegion>(DataReg);
 }
 
-CallEvent::param_iterator BlockCall::param_begin() const {
+CallEvent::param_iterator
+BlockCall::param_begin(bool UseDefinitionParams) const {
+  // Blocks don't have distinct declarations and definitions.
+  (void)UseDefinitionParams;
+
   const BlockDecl *D = getBlockDecl();
   if (!D)
     return 0;
   return D->param_begin();
 }
 
-CallEvent::param_iterator BlockCall::param_end() const {
+CallEvent::param_iterator
+BlockCall::param_end(bool UseDefinitionParams) const {
+  // Blocks don't have distinct declarations and definitions.
+  (void)UseDefinitionParams;
+
   const BlockDecl *D = getBlockDecl();
   if (!D)
     return 0;
@@ -366,32 +384,46 @@
 }
 
 
+SVal CXXConstructorCall::getCXXThisVal() const {
+  if (Target)
+    return loc::MemRegionVal(Target);
+  return UnknownVal();
+}
+
 void CXXConstructorCall::addExtraInvalidatedRegions(RegionList &Regions) const {
   if (Target)
     Regions.push_back(Target);
 }
 
 
+SVal CXXDestructorCall::getCXXThisVal() const {
+  if (Target)
+    return loc::MemRegionVal(Target);
+  return UnknownVal();
+}
+
 void CXXDestructorCall::addExtraInvalidatedRegions(RegionList &Regions) const {
   if (Target)
     Regions.push_back(Target);
 }
 
 
-CallEvent::param_iterator ObjCMethodCall::param_begin() const {
-  const ObjCMethodDecl *D = getDecl();
+CallEvent::param_iterator
+ObjCMethodCall::param_begin(bool UseDefinitionParams) const {
+  const Decl *D = UseDefinitionParams ? getDefinition() : getDecl();
   if (!D)
     return 0;
 
-  return D->param_begin();
+  return cast<ObjCMethodDecl>(D)->param_begin();
 }
 
-CallEvent::param_iterator ObjCMethodCall::param_end() const {
-  const ObjCMethodDecl *D = getDecl();
+CallEvent::param_iterator
+ObjCMethodCall::param_end(bool UseDefinitionParams) const {
+  const Decl *D = UseDefinitionParams ? getDefinition() : getDecl();
   if (!D)
     return 0;
 
-  return D->param_end();
+  return cast<ObjCMethodDecl>(D)->param_end();
 }
 
 void

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=160022&r1=160021&r2=160022&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Tue Jul 10 17:07:57 2012
@@ -55,11 +55,7 @@
   // Construct an edge representing the starting location in the callee.
   BlockEdge Loc(Entry, Succ, calleeCtx);
 
-  // Construct a new state which contains the mapping from actual to
-  // formal arguments.
-  const LocationContext *callerCtx = Pred->getLocationContext();
-  ProgramStateRef state = Pred->getState()->enterStackFrame(callerCtx,
-                                                            calleeCtx);
+  ProgramStateRef state = Pred->getState();
   
   // Construct a new node and add it to the worklist.
   bool isNew;
@@ -287,14 +283,9 @@
   switch (Call.getKind()) {
   case CE_Function:
   case CE_CXXMember:
+  case CE_CXXMemberOperator:
     // These are always at least possible to inline.
     break;
-  case CE_CXXMemberOperator:
-    // FIXME: This should be possible to inline, but
-    // RegionStore::enterStackFrame isn't smart enough to handle the first
-    // argument being 'this'. The correct solution is to use CallEvent in
-    // enterStackFrame as well.
-    return false;
   case CE_CXXConstructor:
   case CE_CXXDestructor:
     // Do not inline constructors until we can really model destructors.
@@ -337,8 +328,13 @@
                              currentStmtIdx);
   
   CallEnter Loc(CallE, CalleeSFC, Pred->getLocationContext());
+
+  // Construct a new state which contains the mapping from actual to
+  // formal arguments.
+  ProgramStateRef State = Pred->getState()->enterStackFrame(Call, CalleeSFC);
+
   bool isNew;
-  if (ExplodedNode *N = G.getNode(Loc, Pred->getState(), false, &isNew)) {
+  if (ExplodedNode *N = G.getNode(Loc, State, false, &isNew)) {
     N->addPredecessor(Pred, G);
     if (isNew)
       Engine.getWorkList()->enqueue(N);

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=160022&r1=160021&r2=160022&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Tue Jul 10 17:07:57 2012
@@ -203,11 +203,11 @@
 }
 
 ProgramStateRef 
-ProgramState::enterStackFrame(const LocationContext *callerCtx,
-                              const StackFrameContext *calleeCtx) const {
-  const StoreRef &new_store =
-    getStateManager().StoreMgr->enterStackFrame(this, callerCtx, calleeCtx);
-  return makeWithStore(new_store);
+ProgramState::enterStackFrame(const CallEvent &Call,
+                              const StackFrameContext *CalleeCtx) const {
+  const StoreRef &NewStore =
+    getStateManager().StoreMgr->enterStackFrame(getStore(), Call, CalleeCtx);
+  return makeWithStore(NewStore);
 }
 
 SVal ProgramState::getSValAsScalarOrLoc(const MemRegion *R) const {

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=160022&r1=160021&r2=160022&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Tue Jul 10 17:07:57 2012
@@ -389,16 +389,6 @@
   ///  It returns a new Store with these values removed.
   StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
                               SymbolReaper& SymReaper);
-
-  StoreRef enterStackFrame(ProgramStateRef state,
-                           const LocationContext *callerCtx,
-                           const StackFrameContext *calleeCtx);
-
-  StoreRef enterStackFrame(ProgramStateRef state,
-                           const FunctionDecl *FD,
-                           const LocationContext *callerCtx,
-                           const StackFrameContext *calleeCtx);
-
   
   //===------------------------------------------------------------------===//
   // Region "extents".
@@ -2066,84 +2056,6 @@
   return StoreRef(B.getRootWithoutRetain(), *this);
 }
 
-StoreRef RegionStoreManager::enterStackFrame(ProgramStateRef state,
-                                             const LocationContext *callerCtx,
-                                             const StackFrameContext *calleeCtx)
-{
-  const Decl *D = calleeCtx->getDecl();
-  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
-    return enterStackFrame(state, FD, callerCtx, calleeCtx);
-  
-  // FIXME: when we handle more cases, this will need to be expanded.
-  
-  const BlockDecl *BD = cast<BlockDecl>(D);
-  BlockDecl::param_const_iterator PI = BD->param_begin(),
-                                  PE = BD->param_end();
-  StoreRef store = StoreRef(state->getStore(), *this);
-  const CallExpr *CE = cast<CallExpr>(calleeCtx->getCallSite());
-  CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
-  for (; AI != AE && PI != PE; ++AI, ++PI) {
-    SVal ArgVal = state->getSVal(*AI, callerCtx);
-    store = Bind(store.getStore(),
-                 svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, calleeCtx)),
-                 ArgVal);
-  }
-  
-  return store;
-}
-
-StoreRef RegionStoreManager::enterStackFrame(ProgramStateRef state,
-                                             const FunctionDecl *FD,
-                                             const LocationContext *callerCtx,
-                                             const StackFrameContext *calleeCtx)
-{
-  FunctionDecl::param_const_iterator PI = FD->param_begin(), 
-                                     PE = FD->param_end();
-  StoreRef store = StoreRef(state->getStore(), *this);
-
-  if (CallExpr const *CE = dyn_cast<CallExpr>(calleeCtx->getCallSite())) {
-    CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end();
-
-    // Copy the arg expression value to the arg variables.  We check that
-    // PI != PE because the actual number of arguments may be different than
-    // the function declaration.
-    for (; AI != AE && PI != PE; ++AI, ++PI) {
-      SVal ArgVal = state->getSVal(*AI, callerCtx);
-      store = Bind(store.getStore(),
-                   svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, calleeCtx)),
-                   ArgVal);
-    }
-
-    // For C++ method calls, also include the 'this' pointer.
-    if (const CXXMemberCallExpr *CME = dyn_cast<CXXMemberCallExpr>(CE)) {
-      loc::MemRegionVal This =
-        svalBuilder.getCXXThis(cast<CXXMethodDecl>(CME->getCalleeDecl()),
-                               calleeCtx);
-      SVal CalledObj = state->getSVal(CME->getImplicitObjectArgument(),
-                                      callerCtx);
-      store = Bind(store.getStore(), This, CalledObj);
-    }
-  }
-  else if (const CXXConstructExpr *CE =
-            dyn_cast<CXXConstructExpr>(calleeCtx->getCallSite())) {
-    CXXConstructExpr::const_arg_iterator AI = CE->arg_begin(),
-      AE = CE->arg_end();
-
-    // Copy the arg expression value to the arg variables.
-    for (; AI != AE; ++AI, ++PI) {
-      SVal ArgVal = state->getSVal(*AI, callerCtx);
-      store = Bind(store.getStore(),
-                   svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, calleeCtx)),
-                   ArgVal);
-    }
-  }
-  else {
-    assert(isa<CXXDestructorDecl>(calleeCtx->getDecl()));
-  }
-
-  return store;
-}
-
 //===----------------------------------------------------------------------===//
 // Utility methods.
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp?rev=160022&r1=160021&r2=160022&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Store.cpp Tue Jul 10 17:07:57 2012
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclObjC.h"
@@ -23,10 +24,36 @@
   : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr),
     MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {}
 
-StoreRef StoreManager::enterStackFrame(ProgramStateRef state,
-                                       const LocationContext *callerCtx,
-                                       const StackFrameContext *calleeCtx) {
-  return StoreRef(state->getStore(), *this);
+StoreRef StoreManager::enterStackFrame(Store OldStore,
+                                       const CallEvent &Call,
+                                       const StackFrameContext *LCtx) {
+  StoreRef Store = StoreRef(OldStore, *this);
+
+  unsigned Idx = 0;
+  for (CallEvent::param_iterator I = Call.param_begin(/*UseDefinition=*/true),
+                                 E = Call.param_end(/*UseDefinition=*/true);
+       I != E; ++I, ++Idx) {
+    const ParmVarDecl *Decl = *I;
+    assert(Decl && "Formal parameter has no decl?");
+
+    SVal ArgVal = Call.getArgSVal(Idx);
+    if (!ArgVal.isUnknown()) {
+      Store = Bind(Store.getStore(),
+                   svalBuilder.makeLoc(MRMgr.getVarRegion(Decl, LCtx)),
+                   ArgVal);
+    }
+  }
+
+  // FIXME: We will eventually want to generalize this to handle other non-
+  // parameter arguments besides 'this' (such as 'self' for ObjC methods).
+  SVal ThisVal = Call.getCXXThisVal();
+  if (!ThisVal.isUndef()) {
+    const CXXMethodDecl *MD = cast<CXXMethodDecl>(Call.getDecl());
+    loc::MemRegionVal ThisRegion = svalBuilder.getCXXThis(MD, LCtx);
+    Store = Bind(Store.getStore(), ThisRegion, ThisVal);
+  }
+
+  return Store;
 }
 
 const MemRegion *StoreManager::MakeElementRegion(const MemRegion *Base,

Modified: cfe/trunk/test/Analysis/operator-calls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/operator-calls.cpp?rev=160022&r1=160021&r2=160022&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/operator-calls.cpp (original)
+++ cfe/trunk/test/Analysis/operator-calls.cpp Tue Jul 10 17:07:57 2012
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-ipa=inlining -verify %s
 void clang_analyzer_eval(bool);
 
 struct X0 { };
@@ -28,6 +28,5 @@
 };
 
 void testMemberOperator(IntComparable B) {
-  // FIXME: Change this to TRUE when we re-enable inlining.
-  clang_analyzer_eval(B == 0); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(B == 0); // expected-warning{{TRUE}}
 }





More information about the cfe-commits mailing list