]> granicus.if.org Git - clang/commitdiff
[analyzer] Make the entries in 'Environment' context-sensitive by making entries...
authorTed Kremenek <kremenek@apple.com>
Fri, 6 Jan 2012 22:09:28 +0000 (22:09 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 6 Jan 2012 22:09:28 +0000 (22:09 +0000)
(Stmt*,LocationContext*) pairs to SVals instead of Stmt* to SVals.

This is needed to support basic IPA via inlining.  Without this, we cannot tell
if a Stmt* binding is part of the current analysis scope (StackFrameContext) or
part of a parent context.

This change introduces an uglification of the use of getSVal(), and thus takes
two steps forward and one step back.  There are also potential performance implications
of enlarging the Environment.  Both can be addressed going forward by refactoring the
APIs and optimizing the internal representation of Environment.  This patch
mainly introduces the functionality upon when we want to build upon (and clean up).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147688 91177308-0d34-0410-b5e6-96231b3b80d8

55 files changed:
include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h
include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp
lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp
lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
lib/StaticAnalyzer/Checkers/CStringChecker.cpp
lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
lib/StaticAnalyzer/Checkers/MallocChecker.cpp
lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp
lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
lib/StaticAnalyzer/Checkers/StreamChecker.cpp
lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
lib/StaticAnalyzer/Core/BugReporter.cpp
lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
lib/StaticAnalyzer/Core/CheckerContext.cpp
lib/StaticAnalyzer/Core/Environment.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
lib/StaticAnalyzer/Core/ExprEngineC.cpp
lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
lib/StaticAnalyzer/Core/ExprEngineObjC.cpp
lib/StaticAnalyzer/Core/ObjCMessage.cpp
lib/StaticAnalyzer/Core/ProgramState.cpp
lib/StaticAnalyzer/Core/RegionStore.cpp
lib/StaticAnalyzer/Core/SymbolManager.cpp

index 3a511821721337fa9048b194d360dd454d88f50e..875df3a4ecd06e9b470b2dfa8ba20882c8b38735 100644 (file)
@@ -16,6 +16,7 @@
 #define LLVM_CLANG_GR_COREENGINE
 
 #include "clang/AST/Expr.h"
+#include "clang/Analysis/AnalysisContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
@@ -469,6 +470,10 @@ public:
   const Expr *getTarget() const { return E; }
 
   const ProgramState *getState() const { return Pred->State; }
+  
+  const LocationContext *getLocationContext() const {
+    return Pred->getLocationContext();
+  }
 };
 
 class SwitchNodeBuilder {
@@ -518,6 +523,10 @@ public:
   const Expr *getCondition() const { return Condition; }
 
   const ProgramState *getState() const { return Pred->State; }
+  
+  const LocationContext *getLocationContext() const {
+    return Pred->getLocationContext();
+  }
 };
 
 class CallEnterNodeBuilder {
index 2463e23f5f792f20c3764c5279cbd7b2a6d92b5c..c58da3ea52de23eeb855fde73c6673ec62588702 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_GR_ENVIRONMENT_H
 #define LLVM_CLANG_GR_ENVIRONMENT_H
 
+#include "clang/Analysis/AnalysisContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "llvm/ADT/ImmutableMap.h"
 
@@ -26,15 +27,39 @@ namespace ento {
 class EnvironmentManager;
 class SValBuilder;
 
-/// Environment - An immutable map from Stmts to their current
-///  symbolic values (SVals).
-///
+/// An entry in the environment consists of a Stmt and an LocationContext.
+/// This allows the environment to manage context-sensitive bindings,
+/// which is essentially for modeling recursive function analysis, among
+/// other things.
+class EnvironmentEntry : public std::pair<const Stmt*,
+                                          const StackFrameContext *> {
+public:
+  EnvironmentEntry(const Stmt *s, const LocationContext *L)
+    : std::pair<const Stmt*,
+                const StackFrameContext*>(s, L ? L->getCurrentStackFrame():0) {}
+
+  const Stmt *getStmt() const { return first; }
+  const LocationContext *getLocationContext() const { return second; }
+  
+  /// Profile an EnvironmentEntry for inclusion in a FoldingSet.
+  static void Profile(llvm::FoldingSetNodeID &ID,
+                      const EnvironmentEntry &E) {
+    ID.AddPointer(E.getStmt());
+    ID.AddPointer(E.getLocationContext());
+  }
+  
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    Profile(ID, *this);
+  }
+};
+
+/// An immutable map from EnvironemntEntries to SVals.
 class Environment {
 private:
   friend class EnvironmentManager;
 
   // Type definitions.
-  typedef llvm::ImmutableMap<const Stmt*,SVal> BindingsTy;
+  typedef llvm::ImmutableMap<EnvironmentEntry, SVal> BindingsTy;
 
   // Data.
   BindingsTy ExprBindings;
@@ -42,18 +67,18 @@ private:
   Environment(BindingsTy eb)
     : ExprBindings(eb) {}
 
-  SVal lookupExpr(const Stmt *E) const;
+  SVal lookupExpr(const EnvironmentEntry &E) const;
 
 public:
   typedef BindingsTy::iterator iterator;
   iterator begin() const { return ExprBindings.begin(); }
   iterator end() const { return ExprBindings.end(); }
 
-
-  /// getSVal - Fetches the current binding of the expression in the
-  ///  Environment.
-  SVal getSVal(const Stmt *Ex, SValBuilder& svalBuilder,
-              bool useOnlyDirectBindings = false) const;
+  /// Fetches the current binding of the expression in the
+  /// Environment.
+  SVal getSVal(const EnvironmentEntry &E,
+               SValBuilder &svalBuilder,
+               bool useOnlyDirectBindings = false) const;
 
   /// Profile - Profile the contents of an Environment object for use
   ///  in a FoldingSet.
@@ -70,6 +95,12 @@ public:
   bool operator==(const Environment& RHS) const {
     return ExprBindings == RHS.ExprBindings;
   }
+  
+  void print(raw_ostream &Out, const char *NL, const char *Sep) const;
+  
+private:
+  void printAux(raw_ostream &Out, bool printLocations,
+                const char *NL, const char *Sep) const;
 };
 
 class EnvironmentManager {
@@ -85,17 +116,20 @@ public:
     return Environment(F.getEmptyMap());
   }
 
-  /// Bind the value 'V' to the statement 'S'.
-  Environment bindExpr(Environment Env, const Stmt *S, SVal V,
+  /// Bind a symbolic value to the given environment entry.
+  Environment bindExpr(Environment Env, const EnvironmentEntry &E, SVal V,
                        bool Invalidate);
   
-  /// Bind the location 'location' and value 'V' to the statement 'S'.  This
-  /// is used when simulating loads/stores.
-  Environment bindExprAndLocation(Environment Env, const Stmt *S, SVal location,
+  /// Bind the location 'location' and value 'V' to the specified
+  /// environment entry.
+  Environment bindExprAndLocation(Environment Env,
+                                  const EnvironmentEntry &E,
+                                  SVal location,
                                   SVal V);
 
   Environment removeDeadBindings(Environment Env,
-                                 SymbolReaper &SymReaper, const ProgramState *ST);
+                                 SymbolReaper &SymReaper,
+                                 const ProgramState *state);
 };
 
 } // end GR namespace
index 3877cb88b418fb4734c643826fea00b8fbf4e2fc..f6d49985cc704d651b4083a8988a2552037794d0 100644 (file)
@@ -433,8 +433,10 @@ protected:
                                           const CallOrObjCMessage &Call,
                                           const LocationContext *LC);
 
-  const ProgramState *MarkBranch(const ProgramState *St, const Stmt *Terminator,
-                            bool branchTaken);
+  const ProgramState *MarkBranch(const ProgramState *state,
+                                 const Stmt *Terminator,
+                                 const LocationContext *LCtx,
+                                 bool branchTaken);
 
   /// evalBind - Handle the semantics of binding a value to a specific location.
   ///  This method is used by evalStore, VisitDeclStmt, and others.
index 500f587e85a705bc0e61cc5ae2700740ac29ccaa..bcaf2591cf2f6fe86e026ea51f7d358c5df02d5a 100644 (file)
@@ -95,7 +95,7 @@ public:
     if (!isInstanceMessage())
       return UndefinedVal();
     if (const Expr *Ex = getInstanceReceiver())
-      return State->getSValAsScalarOrLoc(Ex);
+      return State->getSValAsScalarOrLoc(Ex, LC);
 
     // An instance message with no expression means we are sending to super.
     // In this case the object reference is the same as 'self'.
@@ -141,11 +141,13 @@ public:
     return isPropertySetter() ? 1 : 0;
   }
 
-  SVal getArgSVal(unsigned i, const ProgramState *state) const {
+  SVal getArgSVal(unsigned i,
+                  const LocationContext *LCtx,
+                  const ProgramState *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));
+      return state->getSVal(msgE->getArg(i), LCtx);
     assert(isPropertySetter());
     return SetterArgV;
   }
@@ -207,13 +209,17 @@ class CallOrObjCMessage {
   llvm::PointerUnion<const CallExpr *, const CXXConstructExpr *> CallE;
   ObjCMessage Msg;
   const ProgramState *State;
+  const LocationContext *LCtx;
 public:
-  CallOrObjCMessage(const CallExpr *callE, const ProgramState *state)
-    : CallE(callE), State(state) {}
-  CallOrObjCMessage(const CXXConstructExpr *consE, const ProgramState *state)
-    : CallE(consE), State(state) {}
-  CallOrObjCMessage(const ObjCMessage &msg, const ProgramState *state)
-    : CallE((CallExpr *)0), Msg(msg), State(state) {}
+  CallOrObjCMessage(const CallExpr *callE, const ProgramState *state,
+                    const LocationContext *lctx)
+    : CallE(callE), State(state), LCtx(lctx) {}
+  CallOrObjCMessage(const CXXConstructExpr *consE, const ProgramState *state,
+                    const LocationContext *lctx)
+    : CallE(consE), State(state), LCtx(lctx) {}
+  CallOrObjCMessage(const ObjCMessage &msg, const ProgramState *state,
+                    const LocationContext *lctx)
+    : CallE((CallExpr *)0), Msg(msg), State(state), LCtx(lctx) {}
 
   QualType getResultType(ASTContext &ctx) const;
   
@@ -272,8 +278,8 @@ public:
   SVal getArgSVal(unsigned i) const {
     assert(i < getNumArgs());
     if (!CallE)
-      return Msg.getArgSVal(i, State);
-    return State->getSVal(getArg(i));
+      return Msg.getArgSVal(i, LCtx, State);
+    return State->getSVal(getArg(i), LCtx);
   }
 
   const Expr *getArg(unsigned i) const {
index e9d6d6ec96ea7b6303ca114442df7ebe337091b8..c3396d4eb107241ee696114d51012080099df85f 100644 (file)
@@ -196,12 +196,14 @@ public:
 
   /// Create a new state by binding the value 'V' to the statement 'S' in the
   /// state's environment.
-  const ProgramState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
+  const ProgramState *BindExpr(const Stmt *S, const LocationContext *LCtx,
+                               SVal V, bool Invalidate = true) const;
 
   /// Create a new state by binding the value 'V' and location 'locaton' to the
   /// statement 'S' in the state's environment.
-  const ProgramState *bindExprAndLocation(const Stmt *S, SVal location, SVal V)
-    const;
+  const ProgramState *bindExprAndLocation(const Stmt *S,
+                                          const LocationContext *LCtx,
+                                          SVal location, SVal V) const;
   
   const ProgramState *bindDecl(const VarRegion *VR, SVal V) const;
 
@@ -248,9 +250,10 @@ public:
   const llvm::APSInt *getSymVal(SymbolRef sym) const;
 
   /// Returns the SVal bound to the statement 'S' in the state's environment.
-  SVal getSVal(const Stmt *S, bool useOnlyDirectBindings = false) const;
+  SVal getSVal(const Stmt *S, const LocationContext *LCtx,
+               bool useOnlyDirectBindings = false) const;
   
-  SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
+  SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const;
 
   SVal getSVal(Loc LV, QualType T = QualType()) const;
 
@@ -290,7 +293,7 @@ public:
                        const MemRegion * const *end) const;
 
   /// Create a new state in which the statement is marked as tainted.
-  const ProgramState* addTaint(const Stmt *S,
+  const ProgramState* addTaint(const Stmt *S, const LocationContext *LCtx,
                                TaintTagType Kind = TaintTagGeneric) const;
 
   /// Create a new state in which the symbol is marked as tainted.
@@ -302,7 +305,8 @@ public:
                                TaintTagType Kind = TaintTagGeneric) const;
 
   /// Check if the statement is tainted in the current state.
-  bool isTainted(const Stmt *S, TaintTagType Kind = TaintTagGeneric) const;
+  bool isTainted(const Stmt *S, const LocationContext *LCtx,
+                 TaintTagType Kind = TaintTagGeneric) const;
   bool isTainted(SVal V, TaintTagType Kind = TaintTagGeneric) const;
   bool isTainted(const SymExpr* Sym, TaintTagType Kind = TaintTagGeneric) const;
   bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const;
@@ -361,12 +365,10 @@ public:
   }
 
   // Pretty-printing.
-  void print(raw_ostream &Out, CFG *C, const char *nl = "\n",
+  void print(raw_ostream &Out, const char *nl = "\n",
              const char *sep = "") const;
 
-  void dump(CFG &C) const;
-
-  void printDOT(raw_ostream &Out, CFG &C) const;
+  void printDOT(raw_ostream &Out) const;
 
   void dump() const;
 
@@ -647,7 +649,8 @@ public:
 //===----------------------------------------------------------------------===//
 
 inline const VarRegion* ProgramState::getRegion(const VarDecl *D,
-                                           const LocationContext *LC) const {
+                                                const LocationContext *LC) const 
+{
   return getStateManager().getRegionManager().getVarRegion(D, LC);
 }
 
@@ -705,16 +708,20 @@ inline const llvm::APSInt *ProgramState::getSymVal(SymbolRef sym) const {
   return getStateManager().getSymVal(this, sym);
 }
 
-inline SVal ProgramState::getSVal(const Stmt *Ex, bool useOnlyDirectBindings) const{
-  return Env.getSVal(Ex, *getStateManager().svalBuilder,
+inline SVal ProgramState::getSVal(const Stmt *Ex, const LocationContext *LCtx,
+                                  bool useOnlyDirectBindings) const{
+  return Env.getSVal(EnvironmentEntry(Ex, LCtx),
+                     *getStateManager().svalBuilder,
                      useOnlyDirectBindings);
 }
 
-inline SVal ProgramState::getSValAsScalarOrLoc(const Stmt *S) const {
+inline SVal
+ProgramState::getSValAsScalarOrLoc(const Stmt *S,
+                                   const LocationContext *LCtx) const {
   if (const Expr *Ex = dyn_cast<Expr>(S)) {
     QualType T = Ex->getType();
     if (Ex->isLValue() || Loc::isLocType(T) || T->isIntegerType())
-      return getSVal(S);
+      return getSVal(S, LCtx);
   }
 
   return UnknownVal();
index 32381e7decee2800c286e119df1cf95f7512f298..3690b11eefac1ac77e9cecbb6e4b367cd08ae58a 100644 (file)
@@ -577,7 +577,7 @@ public:
 
   bool isLive(SymbolRef sym);
   bool isLiveRegion(const MemRegion *region);
-  bool isLive(const Stmt *ExprVal) const;
+  bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const;
   bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
 
   /// \brief Unconditionally marks a symbol as live.
index 7dad2421bf57cc0d4ed55b5d113d21641c108979..df5620b803a06aeb496b39b9772b4855e63127a5 100644 (file)
@@ -38,19 +38,20 @@ void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE,
 
   // Fetch the signature of the called function.
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
-  SVal V = state->getSVal(CE);
+  SVal V = state->getSVal(CE, LCtx);
   
   if (V.isUnknown())
     return;
   
   // Casting to void?  Discard the value.
   if (expectedResultTy->isVoidType()) {
-    C.addTransition(state->BindExpr(CE, UnknownVal()));
+    C.addTransition(state->BindExpr(CE, LCtx, UnknownVal()));
     return;
   }                   
 
-  const MemRegion *callee = state->getSVal(CE->getCallee()).getAsRegion();
+  const MemRegion *callee = state->getSVal(CE->getCallee(), LCtx).getAsRegion();
   if (!callee)
     return;
 
@@ -82,7 +83,7 @@ void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE,
     // the cast avoids some assertion failures elsewhere.
     SValBuilder &svalBuilder = C.getSValBuilder();
     V = svalBuilder.evalCast(V, expectedResultTy, actualResultTy);
-    C.addTransition(state->BindExpr(CE, V));
+    C.addTransition(state->BindExpr(CE, LCtx, V));
   }
 }
 
index 8296eb93c5aed18837389eff3475c8e4b1c0e447..a3dc9648f4de1bdacaf7607852d31bc21c827020 100644 (file)
@@ -34,9 +34,10 @@ public:
 void AttrNonNullChecker::checkPreStmt(const CallExpr *CE,
                                       CheckerContext &C) const {
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
   // Check if the callee has a 'nonnull' attribute.
-  SVal X = state->getSVal(CE->getCallee());
+  SVal X = state->getSVal(CE->getCallee(), LCtx);
 
   const FunctionDecl *FD = X.getAsFunctionDecl();
   if (!FD)
@@ -55,7 +56,7 @@ void AttrNonNullChecker::checkPreStmt(const CallExpr *CE,
     if (!Att->isNonNull(idx))
       continue;
 
-    SVal V = state->getSVal(*I);
+    SVal V = state->getSVal(*I, LCtx);
     DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
 
     // If the value is unknown or undefined, we can't perform this check.
index 1f627297ec895b2a83bb896a2c495b0fbb5243e0..fbe4671ddc5239033f249af86ed0a8ba585e45ca 100644 (file)
@@ -129,7 +129,7 @@ void NilArgChecker::checkPreObjCMessage(ObjCMessage msg,
         Name == "compare:options:range:locale:" ||
         Name == "componentsSeparatedByCharactersInSet:" ||
         Name == "initWithFormat:") {
-      if (isNil(msg.getArgSVal(0, C.getState())))
+      if (isNil(msg.getArgSVal(0, C.getLocationContext(), C.getState())))
         WarnNilArg(C, msg, 0);
     }
   }
@@ -262,7 +262,8 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
     return;
 
   // Get the value of the "theType" argument.
-  SVal TheTypeVal = state->getSVal(CE->getArg(1));
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);
 
   // FIXME: We really should allow ranges of valid theType values, and
   //   bifurcate the state appropriately.
@@ -280,7 +281,7 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
   // Look at the value of the integer being passed by reference.  Essentially
   // we want to catch cases where the value passed in is not equal to the
   // size of the type being created.
-  SVal TheValueExpr = state->getSVal(CE->getArg(2));
+  SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);
 
   // FIXME: Eventually we should handle arbitrary locations.  We can do this
   //  by having an enhanced memory model that does low-level typing.
@@ -382,7 +383,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE,
 
   // Get the argument's value.
   const Expr *Arg = CE->getArg(0);
-  SVal ArgVal = state->getSVal(Arg);
+  SVal ArgVal = state->getSVal(Arg, C.getLocationContext());
   DefinedSVal *DefArgVal = dyn_cast<DefinedSVal>(&ArgVal);
   if (!DefArgVal)
     return;
@@ -593,7 +594,8 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg,
       continue;
 
     // Ignore pointer constants.
-    if (isa<loc::ConcreteInt>(msg.getArgSVal(I, state)))
+    if (isa<loc::ConcreteInt>(msg.getArgSVal(I, C.getLocationContext(),
+                                             state)))
       continue;
     
     // Ignore pointer types annotated with 'NSObject' attribute.
index 2cf1209f51d14f4fbedd58e56db2df4f4d4d2d2b..50938fa777b9a27340c92cabc857fb9a63404197 100644 (file)
@@ -33,6 +33,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
                                       CheckerContext &C) const {
   const ProgramState *state = C.getState();
   const FunctionDecl *FD = C.getCalleeDecl(CE);
+  const LocationContext *LCtx = C.getLocationContext();
   if (!FD)
     return false;
 
@@ -45,8 +46,8 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
   case Builtin::BI__builtin_expect: {
     // For __builtin_expect, just return the value of the subexpression.
     assert (CE->arg_begin() != CE->arg_end());
-    SVal X = state->getSVal(*(CE->arg_begin()));
-    C.addTransition(state->BindExpr(CE, X));
+    SVal X = state->getSVal(*(CE->arg_begin()), LCtx);
+    C.addTransition(state->BindExpr(CE, LCtx, X));
     return true;
   }
 
@@ -60,7 +61,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
     // SVal of the argument directly. If we save the extent in bits, we
     // cannot represent values like symbol*8.
     DefinedOrUnknownSVal Size =
-      cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin())));
+      cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin()), LCtx));
 
     SValBuilder& svalBuilder = C.getSValBuilder();
     DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
@@ -68,7 +69,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
       svalBuilder.evalEQ(state, Extent, Size);
     state = state->assume(extentMatchesSizeArg, true);
 
-    C.addTransition(state->BindExpr(CE, loc::MemRegionVal(R)));
+    C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
     return true;
   }
   }
index 49d8bf5388be53fad22525b364ecef4264061da0..bc8d184af7f3a9e67143ad2f293e7e652f434244 100644 (file)
@@ -329,12 +329,13 @@ const ProgramState *CStringChecker::CheckBufferAccess(CheckerContext &C,
 
   SValBuilder &svalBuilder = C.getSValBuilder();
   ASTContext &Ctx = svalBuilder.getContext();
+  const LocationContext *LCtx = C.getLocationContext();
 
   QualType sizeTy = Size->getType();
   QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
 
   // Check that the first buffer is non-null.
-  SVal BufVal = state->getSVal(FirstBuf);
+  SVal BufVal = state->getSVal(FirstBuf, LCtx);
   state = checkNonNull(C, state, FirstBuf, BufVal);
   if (!state)
     return NULL;
@@ -342,7 +343,7 @@ const ProgramState *CStringChecker::CheckBufferAccess(CheckerContext &C,
   // Get the access length and make sure it is known.
   // FIXME: This assumes the caller has already checked that the access length
   // is positive. And that it's unsigned.
-  SVal LengthVal = state->getSVal(Size);
+  SVal LengthVal = state->getSVal(Size, LCtx);
   NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
   if (!Length)
     return state;
@@ -368,7 +369,7 @@ const ProgramState *CStringChecker::CheckBufferAccess(CheckerContext &C,
 
   // If there's a second buffer, check it as well.
   if (SecondBuf) {
-    BufVal = state->getSVal(SecondBuf);
+    BufVal = state->getSVal(SecondBuf, LCtx);
     state = checkNonNull(C, state, SecondBuf, BufVal);
     if (!state)
       return NULL;
@@ -403,8 +404,9 @@ const ProgramState *CStringChecker::CheckOverlap(CheckerContext &C,
   const ProgramState *stateTrue, *stateFalse;
 
   // Get the buffer values and make sure they're known locations.
-  SVal firstVal = state->getSVal(First);
-  SVal secondVal = state->getSVal(Second);
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal firstVal = state->getSVal(First, LCtx);
+  SVal secondVal = state->getSVal(Second, LCtx);
 
   Loc *firstLoc = dyn_cast<Loc>(&firstVal);
   if (!firstLoc)
@@ -456,7 +458,7 @@ const ProgramState *CStringChecker::CheckOverlap(CheckerContext &C,
   }
 
   // Get the length, and make sure it too is known.
-  SVal LengthVal = state->getSVal(Size);
+  SVal LengthVal = state->getSVal(Size, LCtx);
   NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
   if (!Length)
     return state;
@@ -846,7 +848,8 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
   CurrentFunctionDescription = "memory copy function";
 
   // See if the size argument is zero.
-  SVal sizeVal = state->getSVal(Size);
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal sizeVal = state->getSVal(Size, LCtx);
   QualType sizeTy = Size->getType();
 
   const ProgramState *stateZeroSize, *stateNonZeroSize;
@@ -854,12 +857,12 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
     assumeZero(C, state, sizeVal, sizeTy);
 
   // Get the value of the Dest.
-  SVal destVal = state->getSVal(Dest);
+  SVal destVal = state->getSVal(Dest, LCtx);
 
   // If the size is zero, there won't be any actual memory access, so
   // just bind the return value to the destination buffer and return.
   if (stateZeroSize) {
-    stateZeroSize = stateZeroSize->BindExpr(CE, destVal);
+    stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
     C.addTransition(stateZeroSize);
   }
 
@@ -874,7 +877,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
       return;
 
     // Get the value of the Src.
-    SVal srcVal = state->getSVal(Source);
+    SVal srcVal = state->getSVal(Source, LCtx);
     
     // Ensure the source is not null. If it is NULL there will be a
     // NULL pointer dereference.
@@ -910,20 +913,20 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
                                                           Dest->getType());
       
         // The byte after the last byte copied is the return value.
-        state = state->BindExpr(CE, lastElement);
+        state = state->BindExpr(CE, LCtx, lastElement);
       } else {
         // If we don't know how much we copied, we can at least
         // conjure a return value for later.
         unsigned Count = C.getCurrentBlockCount();
         SVal result =
           C.getSValBuilder().getConjuredSymbolVal(NULL, CE, Count);
-        state = state->BindExpr(CE, result);
+        state = state->BindExpr(CE, LCtx, result);
       }
 
     } else {
       // All other copies return the destination buffer.
       // (Well, bcopy() has a void return type, but this won't hurt.)
-      state = state->BindExpr(CE, destVal);
+      state = state->BindExpr(CE, LCtx, destVal);
     }
 
     // Invalidate the destination.
@@ -931,7 +934,8 @@ void CStringChecker::evalCopyCommon(CheckerContext &C,
     // can use LazyCompoundVals to copy the source values into the destination.
     // This would probably remove any existing bindings past the end of the
     // copied region, but that's still an improvement over blank invalidation.
-    state = InvalidateBuffer(C, state, Dest, state->getSVal(Dest));
+    state = InvalidateBuffer(C, state, Dest,
+                             state->getSVal(Dest, C.getLocationContext()));
     C.addTransition(state);
   }
 }
@@ -982,7 +986,8 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
   SValBuilder &svalBuilder = C.getSValBuilder();
 
   // See if the size argument is zero.
-  SVal sizeVal = state->getSVal(Size);
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal sizeVal = state->getSVal(Size, LCtx);
   QualType sizeTy = Size->getType();
 
   const ProgramState *stateZeroSize, *stateNonZeroSize;
@@ -993,7 +998,8 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
   // have to check either of the buffers.
   if (stateZeroSize) {
     state = stateZeroSize;
-    state = state->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType()));
+    state = state->BindExpr(CE, LCtx,
+                            svalBuilder.makeZeroVal(CE->getType()));
     C.addTransition(state);
   }
 
@@ -1003,8 +1009,10 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
     // If we know the two buffers are the same, we know the result is 0.
     // First, get the two buffers' addresses. Another checker will have already
     // made sure they're not undefined.
-    DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left));
-    DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right));
+    DefinedOrUnknownSVal LV =
+      cast<DefinedOrUnknownSVal>(state->getSVal(Left, LCtx));
+    DefinedOrUnknownSVal RV =
+      cast<DefinedOrUnknownSVal>(state->getSVal(Right, LCtx));
 
     // See if they are the same.
     DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
@@ -1017,7 +1025,8 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
       state = StSameBuf;
       state = CheckBufferAccess(C, state, Size, Left);
       if (state) {
-        state = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType()));
+        state = StSameBuf->BindExpr(CE, LCtx,
+                                    svalBuilder.makeZeroVal(CE->getType()));
         C.addTransition(state);
       }
     }
@@ -1031,7 +1040,7 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
         // The return value is the comparison result, which we don't know.
         unsigned Count = C.getCurrentBlockCount();
         SVal CmpV = svalBuilder.getConjuredSymbolVal(NULL, CE, Count);
-        state = state->BindExpr(CE, CmpV);
+        state = state->BindExpr(CE, LCtx, CmpV);
         C.addTransition(state);
       }
     }
@@ -1054,10 +1063,11 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
                                          bool IsStrnlen) const {
   CurrentFunctionDescription = "string length function";
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
   if (IsStrnlen) {
     const Expr *maxlenExpr = CE->getArg(1);
-    SVal maxlenVal = state->getSVal(maxlenExpr);
+    SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
 
     const ProgramState *stateZeroSize, *stateNonZeroSize;
     llvm::tie(stateZeroSize, stateNonZeroSize) =
@@ -1067,7 +1077,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
     // have to check the string itself.
     if (stateZeroSize) {
       SVal zero = C.getSValBuilder().makeZeroVal(CE->getType());
-      stateZeroSize = stateZeroSize->BindExpr(CE, zero);
+      stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
       C.addTransition(stateZeroSize);
     }
 
@@ -1081,7 +1091,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
 
   // Check that the string argument is non-null.
   const Expr *Arg = CE->getArg(0);
-  SVal ArgVal = state->getSVal(Arg);
+  SVal ArgVal = state->getSVal(Arg, LCtx);
 
   state = checkNonNull(C, state, Arg, ArgVal);
 
@@ -1105,7 +1115,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
     // It's a little unfortunate to be getting this again,
     // but it's not that expensive...
     const Expr *maxlenExpr = CE->getArg(1);
-    SVal maxlenVal = state->getSVal(maxlenExpr);
+    SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
 
     NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength);
     NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal);
@@ -1170,7 +1180,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
 
   // Bind the return value.
   assert(!result.isUnknown() && "Should have conjured a value by now");
-  state = state->BindExpr(CE, result);
+  state = state->BindExpr(CE, LCtx, result);
   C.addTransition(state);
 }
 
@@ -1219,10 +1229,11 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
                                       bool isAppending) const {
   CurrentFunctionDescription = "string copy function";
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
   // Check that the destination is non-null.
   const Expr *Dst = CE->getArg(0);
-  SVal DstVal = state->getSVal(Dst);
+  SVal DstVal = state->getSVal(Dst, LCtx);
 
   state = checkNonNull(C, state, Dst, DstVal);
   if (!state)
@@ -1230,7 +1241,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
 
   // Check that the source is non-null.
   const Expr *srcExpr = CE->getArg(1);
-  SVal srcVal = state->getSVal(srcExpr);
+  SVal srcVal = state->getSVal(srcExpr, LCtx);
   state = checkNonNull(C, state, srcExpr, srcVal);
   if (!state)
     return;
@@ -1257,7 +1268,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
   if (isBounded) {
     // Get the max number of characters to copy.
     const Expr *lenExpr = CE->getArg(2);
-    SVal lenVal = state->getSVal(lenExpr);
+    SVal lenVal = state->getSVal(lenExpr, LCtx);
 
     // Protect against misdeclared strncpy().
     lenVal = svalBuilder.evalCast(lenVal, sizeTy, lenExpr->getType());
@@ -1512,7 +1523,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
   }
 
   // Set the return value.
-  state = state->BindExpr(CE, Result);
+  state = state->BindExpr(CE, LCtx, Result);
   C.addTransition(state);
 }
 
@@ -1542,17 +1553,18 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
                                       bool isBounded, bool ignoreCase) const {
   CurrentFunctionDescription = "string comparison function";
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
   // Check that the first string is non-null
   const Expr *s1 = CE->getArg(0);
-  SVal s1Val = state->getSVal(s1);
+  SVal s1Val = state->getSVal(s1, LCtx);
   state = checkNonNull(C, state, s1, s1Val);
   if (!state)
     return;
 
   // Check that the second string is non-null.
   const Expr *s2 = CE->getArg(1);
-  SVal s2Val = state->getSVal(s2);
+  SVal s2Val = state->getSVal(s2, LCtx);
   state = checkNonNull(C, state, s2, s2Val);
   if (!state)
     return;
@@ -1582,7 +1594,8 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
   // If the two arguments might be the same buffer, we know the result is 0,
   // and we only need to check one size.
   if (StSameBuf) {
-    StSameBuf = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType()));
+    StSameBuf = StSameBuf->BindExpr(CE, LCtx,
+                                    svalBuilder.makeZeroVal(CE->getType()));
     C.addTransition(StSameBuf);
 
     // If the two arguments are GUARANTEED to be the same, we're done!
@@ -1608,7 +1621,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
     if (isBounded) {
       // Get the max number of characters to compare.
       const Expr *lenExpr = CE->getArg(2);
-      SVal lenVal = state->getSVal(lenExpr);
+      SVal lenVal = state->getSVal(lenExpr, LCtx);
 
       // If the length is known, we can get the right substrings.
       if (const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
@@ -1645,7 +1658,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
 
       // Build the SVal of the comparison and bind the return value.
       SVal resultVal = svalBuilder.makeIntVal(result, CE->getType());
-      state = state->BindExpr(CE, resultVal);
+      state = state->BindExpr(CE, LCtx, resultVal);
     }
   }
 
@@ -1653,7 +1666,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
     // Conjure a symbolic value. It's the best we can do.
     unsigned Count = C.getCurrentBlockCount();
     SVal resultVal = svalBuilder.getConjuredSymbolVal(NULL, CE, Count);
-    state = state->BindExpr(CE, resultVal);
+    state = state->BindExpr(CE, LCtx, resultVal);
   }
 
   // Record this as a possible path.
@@ -1728,7 +1741,7 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
     if (!MR)
       continue;
 
-    SVal StrVal = state->getSVal(Init);
+    SVal StrVal = state->getSVal(Init, C.getLocationContext());
     assert(StrVal.isValid() && "Initializer string is unknown or undefined");
     DefinedOrUnknownSVal strLength
       = cast<DefinedOrUnknownSVal>(getCStringLength(C, state, Init, StrVal));
index 914b806dd74daa8577dcb6b952ed048f61ed6039..f5f0c1655b960fd47882971a6a5eeda1bac935f6 100644 (file)
@@ -193,7 +193,8 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE,
                                          CheckerContext &C) const{
 
   const Expr *Callee = CE->getCallee()->IgnoreParens();
-  SVal L = C.getState()->getSVal(Callee);
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal L = C.getState()->getSVal(Callee, LCtx);
 
   if (L.isUndef()) {
     if (!BT_call_undef)
@@ -210,7 +211,7 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE,
     EmitBadCall(BT_call_null.get(), C, CE);
   }
 
-  PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState()),
+  PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState(), LCtx),
                       "Function call argument is an uninitialized value",
                       BT_call_arg);
 }
@@ -219,10 +220,11 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
                                                 CheckerContext &C) const {
 
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
 
   // FIXME: Handle 'super'?
   if (const Expr *receiver = msg.getInstanceReceiver()) {
-    SVal recVal = state->getSVal(receiver);
+    SVal recVal = state->getSVal(receiver, LCtx);
     if (recVal.isUndef()) {
       if (ExplodedNode *N = C.generateSink()) {
         if (!BT_msg_undef)
@@ -255,7 +257,8 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg,
                      "Argument for property setter is an uninitialized value"
                    : "Argument in message expression is an uninitialized value";
   // Check for any arguments that are uninitialized/undefined.
-  PreVisitProcessArgs(C, CallOrObjCMessage(msg, state), bugDesc, BT_msg_arg);
+  PreVisitProcessArgs(C, CallOrObjCMessage(msg, state, LCtx),
+                      bugDesc, BT_msg_arg);
 }
 
 void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
@@ -298,11 +301,12 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
   // return different values depending on the return type and the architecture.
   QualType RetTy = msg.getType(Ctx);
   CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
+  const LocationContext *LCtx = C.getLocationContext();
 
   if (CanRetTy->isStructureOrClassType()) {
     // Structure returns are safe since the compiler zeroes them out.
     SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx));
-    C.addTransition(state->BindExpr(msg.getOriginExpr(), V));
+    C.addTransition(state->BindExpr(msg.getOriginExpr(), LCtx, V));
     return;
   }
 
@@ -339,7 +343,7 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
     // of this case unless we have *a lot* more knowledge.
     //
     SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx));
-    C.addTransition(state->BindExpr(msg.getOriginExpr(), V));
+    C.addTransition(state->BindExpr(msg.getOriginExpr(), LCtx, V));
     return;
   }
 
index 84a9e6b3c528e8a3515a83e9584b2e3e8ba1ae66..32b60d91540626c3a5d7bdac4cbf4f1556dcb447 100644 (file)
@@ -45,7 +45,7 @@ void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
     return;
 
   const ProgramState *state = C.getState();
-  const MemRegion *R = state->getSVal(E).getAsRegion();
+  const MemRegion *R = state->getSVal(E, C.getLocationContext()).getAsRegion();
   if (R == 0)
     return;
 
index fa79f2186613f11dbe214bf49c335eee66edeb46..22f7b775a541421752345391bb4fa24f109e4358 100644 (file)
@@ -105,7 +105,7 @@ void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const {
 
   // After chdir("/"), enter the jail, set the enum value JAIL_ENTERED.
   const Expr *ArgExpr = CE->getArg(0);
-  SVal ArgVal = state->getSVal(ArgExpr);
+  SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext());
   
   if (const MemRegion *R = ArgVal.getAsRegion()) {
     R = R->StripCasts();
index d4fbfa14b9ea53e8d82b7b725f980ee36eb32f89..12fd6f4e76d8faa051b0c6f52956932f308a87ff 100644 (file)
@@ -42,7 +42,7 @@ void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
       !B->getRHS()->getType()->isScalarType())
     return;
 
-  SVal Denom = C.getState()->getSVal(B->getRHS());
+  SVal Denom = C.getState()->getSVal(B->getRHS(), C.getLocationContext());
   const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
 
   // Divide-by-undefined handled in the generic checking for uses of
index 7bdd4f34a73e8e5802d95b187bca4b925f8cc77f..d570da001e86284dc9675a78fd2a1a19f109ef50 100644 (file)
@@ -45,8 +45,7 @@ void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
     return;
 
   const ProgramState *state = C.getState();
-
-  SVal RV = state->getSVal(B->getRHS());
+  SVal RV = state->getSVal(B->getRHS(), C.getLocationContext());
 
   if (!RV.isConstant() || RV.isZeroConstant())
     return;
index f09d670c1ff7aa36635383642aad77ee76fe97ef..9e67e21cc3c02e92a65993d920bc21ed618d7556 100644 (file)
@@ -154,7 +154,7 @@ SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C,
                                                   const Expr* Arg,
                                                   bool IssueWarning) const {
   const ProgramState *State = C.getState();
-  SVal AddrVal = State->getSVal(Arg->IgnoreParens());
+  SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext());
   if (AddrVal.isUnknownOrUndef())
     return 0;
 
@@ -185,7 +185,8 @@ const ProgramState *GenericTaintChecker::preFscanf(const CallExpr *CE,
   const ProgramState *State = C.getState();
 
   // Check is the file descriptor is tainted.
-  if (State->isTainted(CE->getArg(0)) || isStdin(CE->getArg(0), C))
+  if (State->isTainted(CE->getArg(0), C.getLocationContext()) ||
+      isStdin(CE->getArg(0), C))
     return State->set<TaintOnPreVisit>(PrevisitTaintArgs);
   return 0;
 }
@@ -196,7 +197,8 @@ const ProgramState * GenericTaintChecker::preAnyArgs(const CallExpr *CE,
   for (unsigned int i = 0; i < CE->getNumArgs(); ++i) {
     const ProgramState *State = C.getState();
     const Expr *Arg = CE->getArg(i);
-    if (State->isTainted(Arg) || State->isTainted(getPointedToSymbol(C, Arg)))
+    if (State->isTainted(Arg, C.getLocationContext()) ||
+        State->isTainted(getPointedToSymbol(C, Arg)))
       return State = State->set<TaintOnPreVisit>(PrevisitTaintRet);
   }
   return 0;
@@ -209,7 +211,7 @@ const ProgramState *GenericTaintChecker::postDefault(const CallExpr *CE,
   // Check if we know that the result needs to be tainted based on the
   // pre-visit analysis.
   if (State->get<TaintOnPreVisit>() == PrevisitTaintRet) {
-    State = State->addTaint(CE);
+    State = State->addTaint(CE, C.getLocationContext());
     return State->set<TaintOnPreVisit>(PrevisitNone);
   }
 
@@ -220,7 +222,7 @@ const ProgramState *GenericTaintChecker::postScanf(const CallExpr *CE,
                                                    CheckerContext &C) const {
   const ProgramState *State = C.getState();
   assert(CE->getNumArgs() >= 2);
-  SVal x = State->getSVal(CE->getArg(1));
+  SVal x = State->getSVal(CE->getArg(1), C.getLocationContext());
   // All arguments except for the very first one should get taint.
   for (unsigned int i = 1; i < CE->getNumArgs(); ++i) {
     // The arguments are pointer arguments. The data they are pointing at is
@@ -262,13 +264,13 @@ const ProgramState *GenericTaintChecker::postFscanf(const CallExpr *CE,
 
 const ProgramState *GenericTaintChecker::postRetTaint(const CallExpr *CE,
                                                       CheckerContext &C) const {
-  return C.getState()->addTaint(CE);
+  return C.getState()->addTaint(CE, C.getLocationContext());
 }
 
 bool GenericTaintChecker::isStdin(const Expr *E,
                                   CheckerContext &C) const {
   const ProgramState *State = C.getState();
-  SVal Val = State->getSVal(E);
+  SVal Val = State->getSVal(E, C.getLocationContext());
 
   // stdin is a pointer, so it would be a region.
   const MemRegion *MemReg = Val.getAsRegion();
index a3ebf0b750aacf13a1d643171d80bc2716cdbb4c..ef830e8684e99e5cf63c157e4e05c6b424d42ac1 100644 (file)
@@ -142,9 +142,9 @@ void IdempotentOperationChecker::checkPreStmt(const BinaryOperator *B,
   }
 
   const ProgramState *state = C.getState();
-
-  SVal LHSVal = state->getSVal(LHS);
-  SVal RHSVal = state->getSVal(RHS);
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal LHSVal = state->getSVal(LHS, LCtx);
+  SVal RHSVal = state->getSVal(RHS, LCtx);
 
   // If either value is unknown, we can't be 100% sure of all paths.
   if (LHSVal.isUnknownOrUndef() || RHSVal.isUnknownOrUndef()) {
index ab3242bdf5b26d008b1e2420d6ad83b5b64f4b15..341d42510b58d294fa6011187db9442b8b1625b7 100644 (file)
@@ -254,7 +254,7 @@ const ProgramState *IteratorsChecker::handleAssign(const ProgramState *state,
     lexp = M->GetTemporaryExpr();
   if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(lexp))
     lexp = ICE->getSubExpr();
-  SVal sv = state->getSVal(lexp);
+  SVal sv = state->getSVal(lexp, LC);
   const MemRegion *MR = sv.getAsRegion();
   if (!MR)
     return state;
@@ -574,7 +574,7 @@ void IteratorsChecker::checkPreStmt(const CXXMemberCallExpr *MCE,
   const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ME->getBase());
   if (!DRE || getTemplateKind(DRE->getType()) != VectorKind)
     return;
-  SVal tsv = C.getState()->getSVal(DRE);
+  SVal tsv = C.getState()->getSVal(DRE, C.getLocationContext());
   // Get the MemRegion associated with the container instance.
   const MemRegion *MR = tsv.getAsRegion();
   if (!MR)
index 78707e7e8ae5abfcbf86dfb75f191814a5afe01b..0a675e562ceeef38fecffc540d93a60af59ab140 100644 (file)
@@ -220,7 +220,7 @@ static bool isBadDeallocationArgument(const MemRegion *Arg) {
 static SymbolRef getAsPointeeSymbol(const Expr *Expr,
                                     CheckerContext &C) {
   const ProgramState *State = C.getState();
-  SVal ArgV = State->getSVal(Expr);
+  SVal ArgV = State->getSVal(Expr, C.getLocationContext());
 
   if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&ArgV)) {
     StoreManager& SM = C.getStoreManager();
@@ -325,7 +325,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
 
   // Check the argument to the deallocator.
   const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param);
-  SVal ArgSVal = State->getSVal(ArgExpr);
+  SVal ArgSVal = State->getSVal(ArgExpr, C.getLocationContext());
 
   // Undef is reported by another checker.
   if (ArgSVal.isUndef())
@@ -462,7 +462,8 @@ void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE,
     // allocated value symbol, since our diagnostics depend on the value
     // returned by the call. Ex: Data should only be freed if noErr was
     // returned during allocation.)
-    SymbolRef RetStatusSymbol = State->getSVal(CE).getAsSymbol();
+    SymbolRef RetStatusSymbol =
+      State->getSVal(CE, C.getLocationContext()).getAsSymbol();
     C.getSymbolManager().addSymbolDependency(V, RetStatusSymbol);
 
     // Track the allocated value in the checker state.
@@ -481,7 +482,8 @@ void MacOSKeychainAPIChecker::checkPreStmt(const ReturnStmt *S,
 
   // Check  if the value is escaping through the return.
   const ProgramState *state = C.getState();
-  const MemRegion *V = state->getSVal(retExpr).getAsRegion();
+  const MemRegion *V =
+    state->getSVal(retExpr, C.getLocationContext()).getAsRegion();
   if (!V)
     return;
   state = state->remove<AllocatedData>(getSymbolForRegion(C, V));
index f8c01047c38c84e8e6a9dd0da4fa590a7a227b4c..9141656f0cbdff35c618d8bfe9ade69ccac711a5 100644 (file)
@@ -57,7 +57,8 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
   // Check if the first argument is stack allocated.  If so, issue a warning
   // because that's likely to be bad news.
   const ProgramState *state = C.getState();
-  const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion();
+  const MemRegion *R =
+    state->getSVal(CE->getArg(0), C.getLocationContext()).getAsRegion();
   if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
     return;
 
index dcc7ab95dc03b39d488bcf50031f45a92d074b91..ea42da40673dba8fe52650e7c6c1fc5447922acd 100644 (file)
@@ -100,7 +100,9 @@ private:
   static const ProgramState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
                                      const Expr *SizeEx, SVal Init,
                                      const ProgramState *state) {
-    return MallocMemAux(C, CE, state->getSVal(SizeEx), Init, state);
+    return MallocMemAux(C, CE,
+                        state->getSVal(SizeEx, C.getLocationContext()),
+                        Init, state);
   }
   static const ProgramState *MallocMemAux(CheckerContext &C, const CallExpr *CE,
                                      SVal SizeEx, SVal Init,
@@ -230,7 +232,7 @@ const ProgramState *MallocChecker::MallocMemAux(CheckerContext &C,
   // Set the return value.
   SVal retVal = svalBuilder.getConjuredSymbolVal(NULL, CE,
                                                  CE->getType(), Count);
-  state = state->BindExpr(CE, retVal);
+  state = state->BindExpr(CE, C.getLocationContext(), retVal);
 
   // Fill the region with the initialization value.
   state = state->bindDefault(retVal, Init);
@@ -280,7 +282,7 @@ const ProgramState *MallocChecker::FreeMemAux(CheckerContext &C,
                                               unsigned Num,
                                               bool Hold) const {
   const Expr *ArgExpr = CE->getArg(Num);
-  SVal ArgVal = state->getSVal(ArgExpr);
+  SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext());
 
   DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(ArgVal);
 
@@ -501,8 +503,9 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
 void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
   const Expr *arg0Expr = CE->getArg(0);
+  const LocationContext *LCtx = C.getLocationContext();
   DefinedOrUnknownSVal arg0Val 
-    = cast<DefinedOrUnknownSVal>(state->getSVal(arg0Expr));
+    = cast<DefinedOrUnknownSVal>(state->getSVal(arg0Expr, LCtx));
 
   SValBuilder &svalBuilder = C.getSValBuilder();
 
@@ -516,7 +519,7 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
 
   // Get the value of the size argument.
   DefinedOrUnknownSVal Arg1Val = 
-    cast<DefinedOrUnknownSVal>(state->getSVal(Arg1));
+    cast<DefinedOrUnknownSVal>(state->getSVal(Arg1, LCtx));
 
   // Compare the size argument to 0.
   DefinedOrUnknownSVal SizeZero =
@@ -548,7 +551,8 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
           FreeMemAux(C, CE, stateSizeZero, 0, false)) {
 
         // Bind the return value to NULL because it is now free.
-        C.addTransition(stateFree->BindExpr(CE, svalBuilder.makeNull(), true));
+        C.addTransition(stateFree->BindExpr(CE, LCtx,
+                                            svalBuilder.makeNull(), true));
       }
     if (const ProgramState *stateSizeNotZero =
           stateNotEqual->assume(SizeZero,false))
@@ -565,9 +569,9 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {
 void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) {
   const ProgramState *state = C.getState();
   SValBuilder &svalBuilder = C.getSValBuilder();
-
-  SVal count = state->getSVal(CE->getArg(0));
-  SVal elementSize = state->getSVal(CE->getArg(1));
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal count = state->getSVal(CE->getArg(0), LCtx);
+  SVal elementSize = state->getSVal(CE->getArg(1), LCtx);
   SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize,
                                         svalBuilder.getContext().getSizeType());  
   SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
@@ -638,7 +642,7 @@ void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
 
   const ProgramState *state = C.getState();
 
-  SymbolRef Sym = state->getSVal(retExpr).getAsSymbol();
+  SymbolRef Sym = state->getSVal(retExpr, C.getLocationContext()).getAsSymbol();
   if (!Sym)
     return;
 
index 81f1924b2c7acc46a469777c9bf0c11cbec0457c..b831a82247621446d38b0048f14de7a681b6aceb 100644 (file)
@@ -42,7 +42,7 @@ void NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE,
   bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();
 
   if (!BuildSinks) {
-    SVal L = state->getSVal(Callee);
+    SVal L = state->getSVal(Callee, C.getLocationContext());
     const FunctionDecl *FD = L.getAsFunctionDecl();
     if (!FD)
       return;
index 27d8fb5abbd1443a3c98c39621febd77cb575d19..4089b346b807e2e875fc1ff93605b30c3afae3de 100644 (file)
@@ -36,9 +36,10 @@ private:
 }
 
 static StringRef getCalleeName(const ProgramState *State,
-                               const CallExpr *CE) {
+                               const CallExpr *CE,
+                               const LocationContext *LCtx) {
   const Expr *Callee = CE->getCallee();
-  SVal L = State->getSVal(Callee);
+  SVal L = State->getSVal(Callee, LCtx);
   const FunctionDecl *funDecl =  L.getAsFunctionDecl();
   if (!funDecl)
     return StringRef();
@@ -52,7 +53,8 @@ bool OSAtomicChecker::inlineCall(const CallExpr *CE,
                                  ExprEngine &Eng,
                                  ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) const {
-  StringRef FName = getCalleeName(Pred->getState(), CE);
+  StringRef FName = getCalleeName(Pred->getState(),
+                                  CE, Pred->getLocationContext());
   if (FName.empty())
     return false;
 
@@ -103,8 +105,9 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE,
   
   // Load 'theValue'.
   const ProgramState *state = Pred->getState();
+  const LocationContext *LCtx = Pred->getLocationContext();
   ExplodedNodeSet Tmp;
-  SVal location = state->getSVal(theValueExpr);
+  SVal location = state->getSVal(theValueExpr, LCtx);
   // Here we should use the value type of the region as the load type, because
   // we are simulating the semantics of the function, not the semantics of 
   // passing argument. So the type of theValue expr is not we are loading.
@@ -135,9 +138,9 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE,
     // Use direct bindings from the environment since we are forcing a load
     // from a location that the Environment would typically not be used
     // to bind a value.
-    SVal theValueVal_untested = stateLoad->getSVal(theValueExpr, true);
+    SVal theValueVal_untested = stateLoad->getSVal(theValueExpr, LCtx, true);
 
-    SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr);
+    SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr, LCtx);
 
     // FIXME: Issue an error.
     if (theValueVal_untested.isUndef() || oldValueVal_untested.isUndef()) {
@@ -161,7 +164,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE,
     if (stateEqual) {
       // Perform the store.
       ExplodedNodeSet TmpStore;
-      SVal val = stateEqual->getSVal(newValueExpr);
+      SVal val = stateEqual->getSVal(newValueExpr, LCtx);
 
       // Handle implicit value casts.
       if (const TypedValueRegion *R =
@@ -189,7 +192,8 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE,
         QualType T = CE->getType();
         if (!T->isVoidType())
           Res = Eng.getSValBuilder().makeTruthVal(true, T);
-        B.generateNode(CE, predNew, stateNew->BindExpr(CE, Res), false, this);
+        B.generateNode(CE, predNew, stateNew->BindExpr(CE, LCtx, Res),
+                       false, this);
       }
     }
 
@@ -201,7 +205,8 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE,
       if (!T->isVoidType())
         Res = Eng.getSValBuilder().makeTruthVal(false, CE->getType());
       StmtNodeBuilder B(N, Dst, Eng.getBuilderContext());    
-      B.generateNode(CE, N, stateNotEqual->BindExpr(CE, Res), false, this);
+      B.generateNode(CE, N, stateNotEqual->BindExpr(CE, LCtx, Res),
+                     false, this);
     }
   }
 
index 5db073c9cb1c13e4034a15c76bdfe87c4551f6d9..06b138e40217bbe2657cb2f22e6bfe07683d929c 100644 (file)
@@ -39,7 +39,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
 
   const Expr *Ex = S->getSynchExpr();
   const ProgramState *state = C.getState();
-  SVal V = state->getSVal(Ex);
+  SVal V = state->getSVal(Ex, C.getLocationContext());
 
   // Uninitialized value used for the mutex?
   if (isa<UndefinedVal>(V)) {
index 8b29a20dc625fcab89227aff882460be9a5b9e7a..a466b41d1257839e7133dd81829c49ce3e4d9ee1 100644 (file)
@@ -156,7 +156,7 @@ static bool hasSelfFlag(SVal val, SelfFlagEnum flag, CheckerContext &C) {
 /// points to and is an object that did not come from the result of calling
 /// an initializer.
 static bool isInvalidSelf(const Expr *E, CheckerContext &C) {
-  SVal exprVal = C.getState()->getSVal(E);
+  SVal exprVal = C.getState()->getSVal(E, C.getLocationContext());
   if (!hasSelfFlag(exprVal, SelfFlag_Self, C))
     return false; // value did not come from 'self'.
   if (hasSelfFlag(exprVal, SelfFlag_InitRes, C))
@@ -206,7 +206,7 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg,
     // value out when we return from this method.
     state = state->set<CalledInit>(true);
     
-    SVal V = state->getSVal(msg.getOriginExpr());
+    SVal V = state->getSVal(msg.getOriginExpr(), C.getLocationContext());
     addSelfFlag(state, V, SelfFlag_InitRes, C);
     return;
   }
@@ -262,7 +262,7 @@ void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
   const ProgramState *state = C.getState();
   for (CallExpr::const_arg_iterator
          I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
-    SVal argV = state->getSVal(*I);
+    SVal argV = state->getSVal(*I, C.getLocationContext());
     if (isSelfVar(argV, C)) {
       unsigned selfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C);
       C.addTransition(state->set<PreCallSelfFlags>(selfFlags));
@@ -278,9 +278,10 @@ void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE,
 void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
                                         CheckerContext &C) const {
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
   for (CallExpr::const_arg_iterator
          I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) {
-    SVal argV = state->getSVal(*I);
+    SVal argV = state->getSVal(*I, LCtx);
     if (isSelfVar(argV, C)) {
       SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
       state = state->remove<PreCallSelfFlags>();
@@ -289,7 +290,7 @@ void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE,
     } else if (hasSelfFlag(argV, SelfFlag_Self, C)) {
       SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>();
       state = state->remove<PreCallSelfFlags>();
-      addSelfFlag(state, state->getSVal(CE), prevFlags, C);
+      addSelfFlag(state, state->getSVal(CE, LCtx), prevFlags, C);
       return;
     }
   }
index 845ae4f0fcc2214558f51feca4cdcc89f8ab1b9f..6adc4dc860168efd6b1009323a94d03d32ee1818 100644 (file)
@@ -37,8 +37,9 @@ void PointerArithChecker::checkPreStmt(const BinaryOperator *B,
     return;
 
   const ProgramState *state = C.getState();
-  SVal LV = state->getSVal(B->getLHS());
-  SVal RV = state->getSVal(B->getRHS());
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal LV = state->getSVal(B->getLHS(), LCtx);
+  SVal RV = state->getSVal(B->getRHS(), LCtx);
 
   const MemRegion *LR = LV.getAsRegion();
 
index 5e5e3e3bfd14b3a4faf1c652d9becbeb7b057736..51f57a20f3ebab86f32fa23503069b41ffffe780 100644 (file)
@@ -40,8 +40,9 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
     return;
 
   const ProgramState *state = C.getState();
-  SVal LV = state->getSVal(B->getLHS());
-  SVal RV = state->getSVal(B->getRHS());
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal LV = state->getSVal(B->getLHS(), LCtx);
+  SVal RV = state->getSVal(B->getRHS(), LCtx);
 
   const MemRegion *LR = LV.getAsRegion();
   const MemRegion *RR = RV.getAsRegion();
index 45988f0a097339f4ee27f431e05f5eb7784d6f6d..a3bbd258591933adb54efa22341044bb534bf7d9 100644 (file)
@@ -57,6 +57,7 @@ template <> struct ProgramStateTrait<LockSet> :
 void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
                                        CheckerContext &C) const {
   const ProgramState *state = C.getState();
+  const LocationContext *LCtx = C.getLocationContext();
   StringRef FName = C.getCalleeName(CE);
   if (FName.empty())
     return;
@@ -67,24 +68,28 @@ void PthreadLockChecker::checkPostStmt(const CallExpr *CE,
   if (FName == "pthread_mutex_lock" ||
       FName == "pthread_rwlock_rdlock" ||
       FName == "pthread_rwlock_wrlock")
-    AcquireLock(C, CE, state->getSVal(CE->getArg(0)), false, PthreadSemantics);
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                false, PthreadSemantics);
   else if (FName == "lck_mtx_lock" ||
            FName == "lck_rw_lock_exclusive" ||
            FName == "lck_rw_lock_shared") 
-    AcquireLock(C, CE, state->getSVal(CE->getArg(0)), false, XNUSemantics);
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                false, XNUSemantics);
   else if (FName == "pthread_mutex_trylock" ||
            FName == "pthread_rwlock_tryrdlock" ||
            FName == "pthread_rwlock_tryrwlock")
-    AcquireLock(C, CE, state->getSVal(CE->getArg(0)), true, PthreadSemantics);
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                true, PthreadSemantics);
   else if (FName == "lck_mtx_try_lock" ||
            FName == "lck_rw_try_lock_exclusive" ||
            FName == "lck_rw_try_lock_shared")
-    AcquireLock(C, CE, state->getSVal(CE->getArg(0)), true, XNUSemantics);
+    AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx),
+                true, XNUSemantics);
   else if (FName == "pthread_mutex_unlock" ||
            FName == "pthread_rwlock_unlock" ||
            FName == "lck_mtx_unlock" ||
            FName == "lck_rw_done")
-    ReleaseLock(C, CE, state->getSVal(CE->getArg(0)));
+    ReleaseLock(C, CE, state->getSVal(CE->getArg(0), LCtx));
 }
 
 void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
@@ -97,7 +102,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
   
   const ProgramState *state = C.getState();
   
-  SVal X = state->getSVal(CE);
+  SVal X = state->getSVal(CE, C.getLocationContext());
   if (X.isUnknownOrUndef())
     return;
   
index 24df0083f507d79fedb2aa1b40de5a75a21904f4..8ba1edbb414dd99973ff1f5cb1dc6aa813cbaf18 100644 (file)
@@ -1312,7 +1312,7 @@ RetainSummaryManager::getInstanceMethodSummary(const ObjCMessage &msg,
   SVal receiverV;
 
   if (Receiver) {
-    receiverV = state->getSValAsScalarOrLoc(Receiver);
+    receiverV = state->getSValAsScalarOrLoc(Receiver, LC);
 
     // FIXME: Eventually replace the use of state->get<RefBindings> with
     // a generic API for reasoning about the Objective-C types of symbolic
@@ -1841,6 +1841,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
   // Check if the type state has changed.
   const ProgramState *PrevSt = PrevN->getState();
   const ProgramState *CurrSt = N->getState();
+  const LocationContext *LCtx = N->getLocationContext();
 
   const RefVal* CurrT = CurrSt->get<RefBindings>(Sym);
   if (!CurrT) return NULL;
@@ -1860,7 +1861,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
 
     if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
       // Get the name of the callee (if it is available).
-      SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee());
+      SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
       if (const FunctionDecl *FD = X.getAsFunctionDecl())
         os << "Call to function '" << *FD << '\'';
       else
@@ -1920,7 +1921,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
 
         // Retrieve the value of the argument.  Is it the symbol
         // we are interested in?
-        if (CurrSt->getSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym)
+        if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
           continue;
 
         // We have an argument.  Get the effect!
@@ -1929,7 +1930,8 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
     }
     else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
       if (const Expr *receiver = ME->getInstanceReceiver())
-        if (CurrSt->getSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) {
+        if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
+              .getAsLocSymbol() == Sym) {
           // The symbol we are tracking is the receiver.
           AEffects.push_back(Summ->getReceiverEffect());
         }
@@ -1957,7 +1959,8 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
     if (contains(AEffects, MakeCollectable)) {
       // Get the name of the function.
       const Stmt *S = cast<StmtPoint>(N->getLocation()).getStmt();
-      SVal X = CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
+      SVal X =
+        CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee(), LCtx);
       const FunctionDecl *FD = X.getAsFunctionDecl();
 
       if (GCEnabled) {
@@ -2069,7 +2072,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N,
   for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
        I!=E; ++I)
     if (const Expr *Exp = dyn_cast_or_null<Expr>(*I))
-      if (CurrSt->getSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) {
+      if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
         P->addRange(Exp->getSourceRange());
         break;
       }
@@ -2505,7 +2508,8 @@ void RetainCountChecker::checkPostStmt(const BlockExpr *BE,
 
   const ProgramState *state = C.getState();
   const BlockDataRegion *R =
-    cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());
+    cast<BlockDataRegion>(state->getSVal(BE,
+                                         C.getLocationContext()).getAsRegion());
 
   BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
                                             E = R->referenced_vars_end();
@@ -2555,7 +2559,7 @@ void RetainCountChecker::checkPostStmt(const CastExpr *CE,
   }
   
   const ProgramState *state = C.getState();
-  SymbolRef Sym = state->getSVal(CE).getAsLocSymbol();
+  SymbolRef Sym = state->getSVal(CE, C.getLocationContext()).getAsLocSymbol();
   if (!Sym)
     return;
   const RefVal* T = state->get<RefBindings>(Sym);
@@ -2579,7 +2583,7 @@ void RetainCountChecker::checkPostStmt(const CallExpr *CE,
   // Get the callee.
   const ProgramState *state = C.getState();
   const Expr *Callee = CE->getCallee();
-  SVal L = state->getSVal(Callee);
+  SVal L = state->getSVal(Callee, C.getLocationContext());
 
   RetainSummaryManager &Summaries = getSummaryManager(C);
   const RetainSummary *Summ = 0;
@@ -2599,7 +2603,7 @@ void RetainCountChecker::checkPostStmt(const CallExpr *CE,
   if (!Summ)
     Summ = Summaries.getDefaultSummary();
 
-  checkSummary(*Summ, CallOrObjCMessage(CE, state), C);
+  checkSummary(*Summ, CallOrObjCMessage(CE, state, C.getLocationContext()), C);
 }
 
 void RetainCountChecker::checkPostStmt(const CXXConstructExpr *CE,
@@ -2616,7 +2620,7 @@ void RetainCountChecker::checkPostStmt(const CXXConstructExpr *CE,
     return;
 
   const ProgramState *state = C.getState();
-  checkSummary(*Summ, CallOrObjCMessage(CE, state), C);
+  checkSummary(*Summ, CallOrObjCMessage(CE, state, C.getLocationContext()), C);
 }
 
 void RetainCountChecker::checkPostObjCMessage(const ObjCMessage &Msg, 
@@ -2637,7 +2641,7 @@ void RetainCountChecker::checkPostObjCMessage(const ObjCMessage &Msg,
   if (!Summ)
     return;
 
-  checkSummary(*Summ, CallOrObjCMessage(Msg, state), C);
+  checkSummary(*Summ, CallOrObjCMessage(Msg, state, C.getLocationContext()), C);
 }
 
 /// GetReturnType - Used to get the return type of a message expression or
@@ -2737,7 +2741,8 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
 
     case RetEffect::OwnedAllocatedSymbol:
     case RetEffect::OwnedSymbol: {
-      SymbolRef Sym = state->getSVal(CallOrMsg.getOriginExpr()).getAsSymbol();
+      SymbolRef Sym = state->getSVal(CallOrMsg.getOriginExpr(),
+                                     C.getLocationContext()).getAsSymbol();
       if (!Sym)
         break;
 
@@ -2764,7 +2769,7 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
     case RetEffect::ARCNotOwnedSymbol:
     case RetEffect::NotOwnedSymbol: {
       const Expr *Ex = CallOrMsg.getOriginExpr();
-      SymbolRef Sym = state->getSVal(Ex).getAsSymbol();
+      SymbolRef Sym = state->getSVal(Ex, C.getLocationContext()).getAsSymbol();
       if (!Sym)
         break;
 
@@ -3030,14 +3035,15 @@ bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
     return false;
 
   // Bind the return value.
-  SVal RetVal = state->getSVal(CE->getArg(0));
+  const LocationContext *LCtx = C.getLocationContext();
+  SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
   if (RetVal.isUnknown()) {
     // If the receiver is unknown, conjure a return value.
     SValBuilder &SVB = C.getSValBuilder();
     unsigned Count = C.getCurrentBlockCount();
     SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count);
   }
-  state = state->BindExpr(CE, RetVal, false);
+  state = state->BindExpr(CE, LCtx, RetVal, false);
 
   // FIXME: This should not be necessary, but otherwise the argument seems to be
   // considered alive during the next statement.
@@ -3072,7 +3078,8 @@ void RetainCountChecker::checkPreStmt(const ReturnStmt *S,
     return;
 
   const ProgramState *state = C.getState();
-  SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol();
+  SymbolRef Sym =
+    state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
   if (!Sym)
     return;
 
index e761bff8558346f2595ca003b528ddd864be7536..f176eecf34feeab4fc3a8c6cc173f1f004080fbc 100644 (file)
@@ -39,7 +39,7 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
   if (!RetE)
     return;
  
-  SVal V = state->getSVal(RetE);
+  SVal V = state->getSVal(RetE, C.getLocationContext());
   const MemRegion *R = V.getAsRegion();
 
   const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R);
index e8c8d902a5e56cc5cc8785095d27a238a33a3aec..e1316b56e7840e5dd964a42793a5bf54c31f5b3f 100644 (file)
@@ -38,7 +38,7 @@ void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS,
   if (!RetE)
     return;
   
-  if (!C.getState()->getSVal(RetE).isUndef())
+  if (!C.getState()->getSVal(RetE, C.getLocationContext()).isUndef())
     return;
   
   ExplodedNode *N = C.generateSink();
index 0d3059e01a77fb8a00f57d33be275ecc7c6e9d38..8eda407f8eeb10f12c1b150641c492a56c39e79b 100644 (file)
@@ -119,7 +119,7 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS,
   if (!RetE)
     return;
  
-  SVal V = C.getState()->getSVal(RetE);
+  SVal V = C.getState()->getSVal(RetE, C.getLocationContext());
   const MemRegion *R = V.getAsRegion();
 
   if (!R || !R->hasStackStorage())
index 2f96bbfeac63c20b611d33a9c08ba3081195c03d..c746c775ab6400c6c56b730751051bfdb0050cef 100644 (file)
@@ -223,7 +223,7 @@ void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const {
   SValBuilder &svalBuilder = C.getSValBuilder();
   DefinedSVal RetVal =
     cast<DefinedSVal>(svalBuilder.getConjuredSymbolVal(0, CE, Count));
-  state = state->BindExpr(CE, RetVal);
+  state = state->BindExpr(CE, C.getLocationContext(), RetVal);
   
   ConstraintManager &CM = C.getConstraintManager();
   // Bifurcate the state into two: one with a valid FILE* pointer, the other
@@ -251,22 +251,25 @@ void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) const {
 
 void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!(state = CheckNullStream(state->getSVal(CE->getArg(0)), state, C)))
+  if (!(state = CheckNullStream(state->getSVal(CE->getArg(0),
+                                               C.getLocationContext()), state, C)))
     return;
   // Check the legality of the 'whence' argument of 'fseek'.
-  SVal Whence = state->getSVal(CE->getArg(2));
+  SVal Whence = state->getSVal(CE->getArg(2), C.getLocationContext());
   const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Whence);
 
   if (!CI)
@@ -289,49 +292,57 @@ void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
 
 void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
 void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const {
   const ProgramState *state = C.getState();
-  if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C))
+  if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()),
+                       state, C))
     return;
 }
 
@@ -361,7 +372,8 @@ const ProgramState *StreamChecker::CheckNullStream(SVal SV, const ProgramState *
 const ProgramState *StreamChecker::CheckDoubleClose(const CallExpr *CE,
                                                const ProgramState *state,
                                                CheckerContext &C) const {
-  SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol();
+  SymbolRef Sym =
+    state->getSVal(CE->getArg(0), C.getLocationContext()).getAsSymbol();
   if (!Sym)
     return state;
   
@@ -442,7 +454,7 @@ void StreamChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const {
     return;
   
   const ProgramState *state = C.getState();
-  SymbolRef Sym = state->getSVal(RetE).getAsSymbol();
+  SymbolRef Sym = state->getSVal(RetE, C.getLocationContext()).getAsSymbol();
   
   if (!Sym)
     return;
index 415346f29c452eac5758f191814868c8af0aa6ee..297beaeedcd72615eb043072f3d221437a8cf948 100644 (file)
@@ -47,7 +47,7 @@ void TaintTesterChecker::checkPostStmt(const Expr *E,
   if (!State)
     return;
 
-  if (State->isTainted(E)) {
+  if (State->isTainted(E, C.getLocationContext())) {
     if (ExplodedNode *N = C.addTransition()) {
       initBugType();
       BugReport *report = new BugReport(*BT, "tainted",N);
index afb79b5d166f3663cf6ad51e7c73743d8503093d..fc0b9c2ec6fd5a4907ceef89d96de2b3a9226efc 100644 (file)
@@ -28,8 +28,10 @@ class UndefBranchChecker : public Checker<check::BranchCondition> {
 
   struct FindUndefExpr {
     const ProgramState *St;
+    const LocationContext *LCtx;
 
-    FindUndefExpr(const ProgramState *S) : St(S) {}
+    FindUndefExpr(const ProgramState *S, const LocationContext *L) 
+      : St(S), LCtx(L) {}
 
     const Expr *FindExpr(const Expr *Ex) {
       if (!MatchesCriteria(Ex))
@@ -45,7 +47,9 @@ class UndefBranchChecker : public Checker<check::BranchCondition> {
       return Ex;
     }
 
-    bool MatchesCriteria(const Expr *Ex) { return St->getSVal(Ex).isUndef(); }
+    bool MatchesCriteria(const Expr *Ex) { 
+      return St->getSVal(Ex, LCtx).isUndef();
+    }
   };
 
 public:
@@ -56,7 +60,7 @@ public:
 
 void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
                                               CheckerContext &Ctx) const {
-  SVal X = Ctx.getState()->getSVal(Condition);
+  SVal X = Ctx.getState()->getSVal(Condition, Ctx.getLocationContext());
   if (X.isUndef()) {
     // Generate a sink node, which implicitly marks both outgoing branches as
     // infeasible.
@@ -90,7 +94,7 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
         if (PS->getStmt() == Ex)
           St = PrevN->getState();
 
-      FindUndefExpr FindIt(St);
+      FindUndefExpr FindIt(St, Ctx.getLocationContext());
       Ex = FindIt.FindExpr(Ex);
 
       // Emit the bug report.
index 82c9fd4a86be19582078f29f1333f33deaeeda37..60f1f5b8e345c2a445f361c4bd15cc10d9ceadfc 100644 (file)
@@ -57,7 +57,8 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
 
   const ProgramState *state = C.getState();
   const BlockDataRegion *R =
-    cast<BlockDataRegion>(state->getSVal(BE).getAsRegion());
+    cast<BlockDataRegion>(state->getSVal(BE,
+                                         C.getLocationContext()).getAsRegion());
 
   BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(),
                                             E = R->referenced_vars_end();
index 7ae966865c864237c2065b7417621a89522d2f03..b074ff918e8d90b61f0005bbfc3a55ba595756fe 100644 (file)
@@ -36,7 +36,8 @@ public:
 void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
                                        CheckerContext &C) const {
   const ProgramState *state = C.getState();
-  if (state->getSVal(B).isUndef()) {
+  const LocationContext *LCtx = C.getLocationContext();
+  if (state->getSVal(B, LCtx).isUndef()) {
     // Generate an error node.
     ExplodedNode *N = C.generateSink();
     if (!N)
@@ -50,11 +51,11 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
     const Expr *Ex = NULL;
     bool isLeft = true;
     
-    if (state->getSVal(B->getLHS()).isUndef()) {
+    if (state->getSVal(B->getLHS(), LCtx).isUndef()) {
       Ex = B->getLHS()->IgnoreParenCasts();
       isLeft = true;
     }
-    else if (state->getSVal(B->getRHS()).isUndef()) {
+    else if (state->getSVal(B->getRHS(), LCtx).isUndef()) {
       Ex = B->getRHS()->IgnoreParenCasts();
       isLeft = false;
     }
index bb6831b783014411cd4260826bcfa9168ae39f01..ee58a043cc0e0fc64b23f367426ad731c628fc0e 100644 (file)
@@ -34,7 +34,7 @@ public:
 void 
 UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
                                              CheckerContext &C) const {
-  if (C.getState()->getSVal(A->getIdx()).isUndef()) {
+  if (C.getState()->getSVal(A->getIdx(), C.getLocationContext()).isUndef()) {
     if (ExplodedNode *N = C.generateSink()) {
       if (!BT)
         BT.reset(new BuiltinBug("Array subscript is undefined"));
index 5ca4a9fe46d2f110baf180a585b31bee0db1e89b..bb9eeb1fa8c1d8ebd64e749229a039c4fc856d96 100644 (file)
@@ -55,7 +55,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
     if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
       if (B->isCompoundAssignmentOp()) {
         const ProgramState *state = C.getState();
-        if (state->getSVal(B->getLHS()).isUndef()) {
+        if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) {
           str = "The left expression of the compound assignment is an "
                 "uninitialized value. The computed value will also be garbage";
           ex = B->getLHS();
index 28ff6971a24d13cd9c42c02d2aaa3ae9b180b51a..420acd5aacdbabf1d6572041504660579344cb67 100644 (file)
@@ -91,7 +91,7 @@ void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
 
   // Now check if oflags has O_CREAT set.
   const Expr *oflagsEx = CE->getArg(1);
-  const SVal V = state->getSVal(oflagsEx);
+  const SVal V = state->getSVal(oflagsEx, C.getLocationContext());
   if (!isa<NonLoc>(V)) {
     // The case where 'V' can be a location can only be due to a bad header,
     // so in this case bail out.
@@ -149,7 +149,8 @@ void UnixAPIChecker::CheckPthreadOnce(CheckerContext &C,
   // Check if the first argument is stack allocated.  If so, issue a warning
   // because that's likely to be bad news.
   const ProgramState *state = C.getState();
-  const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion();
+  const MemRegion *R =
+    state->getSVal(CE->getArg(0), C.getLocationContext()).getAsRegion();
   if (!R || !isa<StackSpaceRegion>(R->getMemorySpace()))
     return;
 
@@ -229,7 +230,7 @@ void UnixAPIChecker::CheckCallocZero(CheckerContext &C,
   unsigned int i;
   for (i = 0; i < nArgs; i++) {
     const Expr *arg = CE->getArg(i);
-    SVal argVal = state->getSVal(arg);
+    SVal argVal = state->getSVal(arg, C.getLocationContext());
     if (argVal.isUnknownOrUndef()) {
       if (i == 0)
         continue;
@@ -265,7 +266,7 @@ void UnixAPIChecker::CheckMallocZero(CheckerContext &C,
   const ProgramState *state = C.getState();
   const ProgramState *trueState = NULL, *falseState = NULL;
   const Expr *arg = CE->getArg(0);
-  SVal argVal = state->getSVal(arg);
+  SVal argVal = state->getSVal(arg, C.getLocationContext());
 
   if (argVal.isUnknownOrUndef())
     return;
@@ -289,7 +290,7 @@ void UnixAPIChecker::CheckReallocZero(CheckerContext &C,
   const ProgramState *state = C.getState();
   const ProgramState *trueState = NULL, *falseState = NULL;
   const Expr *arg = CE->getArg(1);
-  SVal argVal = state->getSVal(arg);
+  SVal argVal = state->getSVal(arg, C.getLocationContext());
 
   if (argVal.isUnknownOrUndef())
     return;
index 969a896b63bbf238fba724f67a04f5b0f52b956f..0308bf5c11b6365dd846c1febb0ce27062f01d22 100644 (file)
@@ -50,7 +50,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
   // FIXME: Handle multi-dimensional VLAs.
   const Expr *SE = VLA->getSizeExpr();
   const ProgramState *state = C.getState();
-  SVal sizeV = state->getSVal(SE);
+  SVal sizeV = state->getSVal(SE, C.getLocationContext());
 
   if (sizeV.isUndef()) {
     // Generate an error node.
index 8ef9c21913cb228f157942dd4238b30b09de837f..38be3895d4e8ad45989c546d92cf7a99c7b0054a 100644 (file)
@@ -343,7 +343,7 @@ static const VarDecl* GetMostRecentVarDeclBinding(const ExplodedNode *N,
     if (!DR)
       continue;
 
-    SVal Y = N->getState()->getSVal(DR);
+    SVal Y = N->getState()->getSVal(DR, N->getLocationContext());
 
     if (X != Y)
       continue;
index 88f38a3e4b487ac3907556ddec02f91e2d8b5076..b27595a41b629c94ca6a96f5031c33c6354f0674 100644 (file)
@@ -339,7 +339,7 @@ bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N,
     }
   }
 
-  SVal V = state->getSValAsScalarOrLoc(S);
+  SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext());
 
   // Uncomment this to find cases where we aren't properly getting the
   // base value that was dereferenced.
@@ -389,7 +389,7 @@ PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
   if (!Receiver)
     return 0;
   const ProgramState *state = N->getState();
-  const SVal &V = state->getSVal(Receiver);
+  const SVal &V = state->getSVal(Receiver, N->getLocationContext());
   const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V);
   if (!DV)
     return 0;
@@ -428,7 +428,7 @@ void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
         StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext());
 
         // What did we load?
-        SVal V = state->getSVal(S);
+        SVal V = state->getSVal(S, N->getLocationContext());
 
         if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) {
           // Register a new visitor with the BugReport.
index 5552a991d150dfb3e59f14f29915bdcd06146f89..3737ca5467257967607caa9dda73f519d6cee1b6 100644 (file)
@@ -19,7 +19,7 @@ using namespace ento;
 const FunctionDecl *CheckerContext::getCalleeDecl(const CallExpr *CE) const {
   const ProgramState *State = getState();
   const Expr *Callee = CE->getCallee();
-  SVal L = State->getSVal(Callee);
+  SVal L = State->getSVal(Callee, Pred->getLocationContext());
   return L.getAsFunctionDecl();
 }
 
index e1b982c08cfc0f11b2380434531bc3fd6d43fd89..f43c2adc6498b1e798845eba2060bf71ce8c584b 100644 (file)
@@ -19,7 +19,7 @@
 using namespace clang;
 using namespace ento;
 
-SVal Environment::lookupExpr(const Stmt *E) const {
+SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
   const SVal* X = ExprBindings.lookup(E);
   if (X) {
     SVal V = *X;
@@ -28,17 +28,21 @@ SVal Environment::lookupExpr(const Stmt *E) const {
   return UnknownVal();
 }
 
-SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder,
-                         bool useOnlyDirectBindings) const {
+SVal Environment::getSVal(const EnvironmentEntry &Entry,
+                          SValBuilder& svalBuilder,
+                          bool useOnlyDirectBindings) const {
 
   if (useOnlyDirectBindings) {
     // This branch is rarely taken, but can be exercised by
     // checkers that explicitly bind values to arbitrary
     // expressions.  It is crucial that we do not ignore any
     // expression here, and do a direct lookup.
-    return lookupExpr(E);
+    return lookupExpr(Entry);
   }
 
+  const Stmt *E = Entry.getStmt();
+  const LocationContext *LCtx = Entry.getLocationContext();
+  
   for (;;) {
     if (const Expr *Ex = dyn_cast<Expr>(E))
       E = Ex->IgnoreParens();
@@ -61,7 +65,7 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder,
         return svalBuilder.makeIntVal(C->getValue(), C->getType());
       }
       case Stmt::CXXBoolLiteralExprClass: {
-        const SVal *X = ExprBindings.lookup(E);
+        const SVal *X = ExprBindings.lookup(EnvironmentEntry(E, LCtx));
         if (X) 
           return *X;
         else 
@@ -69,7 +73,7 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder,
       }
       case Stmt::IntegerLiteralClass: {
         // In C++, this expression may have been bound to a temporary object.
-        SVal const *X = ExprBindings.lookup(E);
+        SVal const *X = ExprBindings.lookup(EnvironmentEntry(E, LCtx));
         if (X)
           return *X;
         else
@@ -93,32 +97,33 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder,
     };
     break;
   }
-  return lookupExpr(E);
+  return lookupExpr(EnvironmentEntry(E, LCtx));
 }
 
-Environment EnvironmentManager::bindExpr(Environment Env, const Stmt *S,
-                                         SVal V, bool Invalidate) {
-  assert(S);
-
+Environment EnvironmentManager::bindExpr(Environment Env,
+                                         const EnvironmentEntry &E,
+                                         SVal V,
+                                         bool Invalidate) {
   if (V.isUnknown()) {
     if (Invalidate)
-      return Environment(F.remove(Env.ExprBindings, S));
+      return Environment(F.remove(Env.ExprBindings, E));
     else
       return Env;
   }
-
-  return Environment(F.add(Env.ExprBindings, S, V));
+  return Environment(F.add(Env.ExprBindings, E, V));
 }
 
-static inline const Stmt *MakeLocation(const Stmt *S) {
-  return (const Stmt*) (((uintptr_t) S) | 0x1);
+static inline EnvironmentEntry MakeLocation(const EnvironmentEntry &E) {
+  const Stmt *S = E.getStmt();
+  S = (const Stmt*) (((uintptr_t) S) | 0x1);
+  return EnvironmentEntry(S, E.getLocationContext());
 }
 
 Environment EnvironmentManager::bindExprAndLocation(Environment Env,
-                                                    const Stmt *S,
+                                                    const EnvironmentEntry &E,
                                                     SVal location, SVal V) {
-  return Environment(F.add(F.add(Env.ExprBindings, MakeLocation(S), location),
-                           S, V));
+  return Environment(F.add(F.add(Env.ExprBindings, MakeLocation(E), location),
+                           E, V));
 }
 
 namespace {
@@ -130,10 +135,11 @@ public:
 };
 } // end anonymous namespace
 
-// In addition to mapping from Stmt * - > SVals in the Environment, we also
-// maintain a mapping from Stmt * -> SVals (locations) that were used during
-// a load and store.
-static inline bool IsLocation(const Stmt *S) {
+// In addition to mapping from EnvironmentEntry - > SVals in the Environment,
+// we also maintain a mapping from EnvironmentEntry -> SVals (locations)
+// that were used during a load and store.
+static inline bool IsLocation(const EnvironmentEntry &E) {
+  const Stmt *S = E.getStmt();
   return (bool) (((uintptr_t) S) & 0x1);
 }
 
@@ -154,12 +160,12 @@ EnvironmentManager::removeDeadBindings(Environment Env,
   // outnumber block-level expression bindings).
   Environment NewEnv = getInitialEnvironment();
   
-  SmallVector<std::pair<const Stmt*, SVal>, 10> deferredLocations;
+  SmallVector<std::pair<EnvironmentEntry, SVal>, 10> deferredLocations;
 
   MarkLiveCallback CB(SymReaper);
   ScanReachableSymbols RSScaner(ST, CB);
 
-  llvm::ImmutableMapRef<const Stmt*,SVal>
+  llvm::ImmutableMapRef<EnvironmentEntry,SVal>
     EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),
              F.getTreeFactory());
 
@@ -167,7 +173,7 @@ EnvironmentManager::removeDeadBindings(Environment Env,
   for (Environment::iterator I = Env.begin(), E = Env.end();
        I != E; ++I) {
 
-    const Stmt *BlkExpr = I.getKey();
+    const EnvironmentEntry &BlkExpr = I.getKey();
     // For recorded locations (used when evaluating loads and stores), we
     // consider them live only when their associated normal expression is
     // also live.
@@ -179,7 +185,7 @@ EnvironmentManager::removeDeadBindings(Environment Env,
     }
     const SVal &X = I.getData();
 
-    if (SymReaper.isLive(BlkExpr)) {
+    if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) {
       // Copy the binding to the new map.
       EBMapRef = EBMapRef.add(BlkExpr, X);
 
@@ -204,13 +210,58 @@ EnvironmentManager::removeDeadBindings(Environment Env,
   
   // Go through he deferred locations and add them to the new environment if
   // the correspond Stmt* is in the map as well.
-  for (SmallVectorImpl<std::pair<const Stmt*, SVal> >::iterator
+  for (SmallVectorImpl<std::pair<EnvironmentEntry, SVal> >::iterator
       I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) {
-    const Stmt *S = (Stmt*) (((uintptr_t) I->first) & (uintptr_t) ~0x1);
-    if (EBMapRef.lookup(S))
-      EBMapRef = EBMapRef.add(I->first, I->second);
+    const EnvironmentEntry &En = I->first;
+    const Stmt *S = (Stmt*) (((uintptr_t) En.getStmt()) & (uintptr_t) ~0x1);
+    if (EBMapRef.lookup(EnvironmentEntry(S, En.getLocationContext())))
+      EBMapRef = EBMapRef.add(En, I->second);
   }
 
   NewEnv.ExprBindings = EBMapRef.asImmutableMap();
   return NewEnv;
 }
+
+void Environment::print(raw_ostream &Out, const char *NL,
+                        const char *Sep) const {
+  printAux(Out, false, NL, Sep);
+  printAux(Out, true, NL, Sep);
+}
+  
+void Environment::printAux(raw_ostream &Out, bool printLocations,
+                           const char *NL,
+                           const char *Sep) const{
+
+  bool isFirst = true;
+
+  for (Environment::iterator I = begin(), E = end(); I != E; ++I) {
+    const EnvironmentEntry &En = I.getKey();
+    if (IsLocation(En)) {
+      if (!printLocations)
+        continue;
+    }
+    else {
+      if (printLocations)
+        continue;
+    }
+    
+    if (isFirst) {
+      Out << NL << NL
+          << (printLocations ? "Load/Store locations:" : "Expressions:")
+          << NL;      
+      isFirst = false;
+    } else {
+      Out << NL;
+    }
+    
+    const Stmt *S = En.getStmt();
+    if (printLocations) {
+      S = (Stmt*) (((uintptr_t) S) & ((uintptr_t) ~0x1));
+    }
+    
+    Out << " (" << (void*) En.getLocationContext() << ',' << (void*) S << ") ";
+    LangOptions LO; // FIXME.
+    S->printPretty(Out, 0, PrintingPolicy(LO));
+    Out << " : " << I.getData();
+  }
+}
index f7022c6482c263d38deffe1f95ecc067b4ebafcb..2ab501a2677c44477e4028c02ee712f5c0e93858 100644 (file)
@@ -366,7 +366,7 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
       const FieldDecl *FD = BMI->getAnyMember();
 
       SVal FieldLoc = state->getLValue(FD, thisVal);
-      SVal InitVal = state->getSVal(BMI->getInit());
+      SVal InitVal = state->getSVal(BMI->getInit(), Pred->getLocationContext());
       state = state->bindLoc(FieldLoc, InitVal);
 
       // Use a custom node building process.
@@ -534,7 +534,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::GNUNullExprClass: {
       // GNU __null is a pointer-width integer, not an actual pointer.
       const ProgramState *state = Pred->getState();
-      state = state->BindExpr(S, svalBuilder.makeIntValWithPtrWidth(0, false));
+      state = state->BindExpr(S, Pred->getLocationContext(),
+                              svalBuilder.makeIntValWithPtrWidth(0, false));
       Bldr.generateNode(S, Pred, state);
       break;
     }
@@ -553,7 +554,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       const ProgramState *state = Pred->getState();
       QualType ty = cast<ImplicitValueInitExpr>(S)->getType();
       SVal val = svalBuilder.makeZeroVal(ty);
-      Bldr.generateNode(S, Pred, state->BindExpr(S, val));
+      Bldr.generateNode(S, Pred, state->BindExpr(S, Pred->getLocationContext(),
+                                                 val));
       break;
     }
       
@@ -635,7 +637,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       else if (B->getOpcode() == BO_Comma) {
         const ProgramState *state = Pred->getState();
         Bldr.generateNode(B, Pred,
-                          state->BindExpr(B, state->getSVal(B->getRHS())));
+                          state->BindExpr(B, Pred->getLocationContext(),
+                                          state->getSVal(B->getRHS(),
+                                                  Pred->getLocationContext())));
         break;
       }
 
@@ -850,7 +854,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       if (Expr *LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
         const ProgramState *state = Pred->getState();
         Bldr.generateNode(SE, Pred,
-                          state->BindExpr(SE, state->getSVal(LastExpr)));
+                          state->BindExpr(SE, Pred->getLocationContext(),
+                                          state->getSVal(LastExpr,
+                                                  Pred->getLocationContext())));
       }
       break;
     }
@@ -858,7 +864,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::StringLiteralClass: {
       const ProgramState *state = Pred->getState();
       SVal V = state->getLValue(cast<StringLiteral>(S));
-      Bldr.generateNode(S, Pred, state->BindExpr(S, V));
+      Bldr.generateNode(S, Pred, state->BindExpr(S, Pred->getLocationContext(),
+                                                 V));
       return;
     }
 
@@ -881,11 +888,14 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       const ProgramState *state = Pred->getState();
       const PseudoObjectExpr *PE = cast<PseudoObjectExpr>(S);
       if (const Expr *Result = PE->getResultExpr()) { 
-        SVal V = state->getSVal(Result);
-        Bldr.generateNode(S, Pred, state->BindExpr(S, V));
+        SVal V = state->getSVal(Result, Pred->getLocationContext());
+        Bldr.generateNode(S, Pred,
+                          state->BindExpr(S, Pred->getLocationContext(), V));
       }
       else
-        Bldr.generateNode(S, Pred, state->BindExpr(S, UnknownVal()));
+        Bldr.generateNode(S, Pred,
+                          state->BindExpr(S, Pred->getLocationContext(),
+                                                   UnknownVal()));
 
       Bldr.addNodes(Dst);
       break;
@@ -910,8 +920,9 @@ void ExprEngine::processCFGBlockEntrance(NodeBuilderWithSinks &nodeBuilder) {
 //===----------------------------------------------------------------------===//
 
 const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
-                                        const Stmt *Terminator,
-                                        bool branchTaken) {
+                                           const Stmt *Terminator,
+                                           const LocationContext *LCtx,
+                                           bool branchTaken) {
 
   switch (Terminator->getStmtClass()) {
     default:
@@ -934,7 +945,7 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
                        (Op == BO_LOr && !branchTaken)
                        ? B->getRHS() : B->getLHS();
 
-      return state->BindExpr(B, UndefinedVal(Ex));
+      return state->BindExpr(B, LCtx, UndefinedVal(Ex));
     }
 
     case Stmt::BinaryConditionalOperatorClass:
@@ -952,7 +963,7 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
       else
         Ex = C->getFalseExpr();
 
-      return state->BindExpr(C, UndefinedVal(Ex));
+      return state->BindExpr(C, LCtx, UndefinedVal(Ex));
     }
 
     case Stmt::ChooseExprClass: { // ?:
@@ -960,7 +971,7 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
       const ChooseExpr *C = cast<ChooseExpr>(Terminator);
 
       const Expr *Ex = branchTaken ? C->getLHS() : C->getRHS();
-      return state->BindExpr(C, UndefinedVal(Ex));
+      return state->BindExpr(C, LCtx, UndefinedVal(Ex));
     }
   }
 }
@@ -973,6 +984,7 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state,
 static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
                                 const ProgramState *state,
                                 const Stmt *Condition,
+                                const LocationContext *LCtx,
                                 ASTContext &Ctx) {
 
   const Expr *Ex = dyn_cast<Expr>(Condition);
@@ -1003,7 +1015,7 @@ static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
   if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits)
     return UnknownVal();
 
-  return state->getSVal(Ex);
+  return state->getSVal(Ex, LCtx);
 }
 
 void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
@@ -1042,7 +1054,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
       continue;
 
     const ProgramState *PrevState = Pred->getState();
-    SVal X = PrevState->getSVal(Condition);
+    SVal X = PrevState->getSVal(Condition, Pred->getLocationContext());
 
     if (X.isUnknownOrUndef()) {
       // Give it a chance to recover from unknown.
@@ -1054,6 +1066,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
           // underlying value and use that instead.
           SVal recovered = RecoverCastedSymbol(getStateManager(),
                                                PrevState, Condition,
+                                               Pred->getLocationContext(),
                                                getContext());
 
           if (!recovered.isUnknown()) {
@@ -1062,10 +1075,15 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
         }
       }
     }
+    
+    const LocationContext *LCtx = PredI->getLocationContext();
+
     // If the condition is still unknown, give up.
     if (X.isUnknownOrUndef()) {
-      builder.generateNode(MarkBranch(PrevState, Term, true), true, PredI);
-      builder.generateNode(MarkBranch(PrevState, Term, false), false, PredI);
+      builder.generateNode(MarkBranch(PrevState, Term, LCtx, true),
+                           true, PredI);
+      builder.generateNode(MarkBranch(PrevState, Term, LCtx, false),
+                           false, PredI);
       continue;
     }
 
@@ -1074,7 +1092,8 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
     // Process the true branch.
     if (builder.isFeasible(true)) {
       if (const ProgramState *state = PrevState->assume(V, true))
-        builder.generateNode(MarkBranch(state, Term, true), true, PredI);
+        builder.generateNode(MarkBranch(state, Term, LCtx, true),
+                             true, PredI);
       else
         builder.markInfeasible(true);
     }
@@ -1082,7 +1101,8 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
     // Process the false branch.
     if (builder.isFeasible(false)) {
       if (const ProgramState *state = PrevState->assume(V, false))
-        builder.generateNode(MarkBranch(state, Term, false), false, PredI);
+        builder.generateNode(MarkBranch(state, Term, LCtx, false),
+                             false, PredI);
       else
         builder.markInfeasible(false);
     }
@@ -1095,7 +1115,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
 void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
 
   const ProgramState *state = builder.getState();
-  SVal V = state->getSVal(builder.getTarget());
+  SVal V = state->getSVal(builder.getTarget(), builder.getLocationContext());
 
   // Three possibilities:
   //
@@ -1149,7 +1169,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
   typedef SwitchNodeBuilder::iterator iterator;
   const ProgramState *state = builder.getState();
   const Expr *CondE = builder.getCondition();
-  SVal  CondV_untested = state->getSVal(CondE);
+  SVal  CondV_untested = state->getSVal(CondE, builder.getLocationContext());
 
   if (CondV_untested.isUndef()) {
     //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
@@ -1256,6 +1276,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
 
   const ProgramState *state = Pred->getState();
+  const LocationContext *LCtx = Pred->getLocationContext();
 
   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
     assert(Ex->isLValue());
@@ -1270,19 +1291,19 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
         V = UnknownVal();
     }
 
-    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, V), false, 0,
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), false, 0,
                       ProgramPoint::PostLValueKind);
     return;
   }
   if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) {
     assert(!Ex->isLValue());
     SVal V = svalBuilder.makeIntVal(ED->getInitVal());
-    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, V));
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));
     return;
   }
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     SVal V = svalBuilder.getFunctionPointer(FD);
-    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, V), false, 0,
+    Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), false, 0,
                       ProgramPoint::PostLValueKind);
     return;
   }
@@ -1306,11 +1327,13 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
 
   for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(),
                                  ei = checkerPreStmt.end(); it != ei; ++it) {
+    const LocationContext *LCtx = (*it)->getLocationContext();
     const ProgramState *state = (*it)->getState();
-    SVal V = state->getLValue(A->getType(), state->getSVal(Idx),
-                              state->getSVal(Base));
+    SVal V = state->getLValue(A->getType(),
+                              state->getSVal(Idx, LCtx),
+                              state->getSVal(Base, LCtx));
     assert(A->isLValue());
-    Bldr.generateNode(A, *it, state->BindExpr(A, V),
+    Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V),
                       false, 0, ProgramPoint::PostLValueKind);
   }
 }
@@ -1336,14 +1359,15 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
 
   Expr *baseExpr = M->getBase()->IgnoreParens();
   const ProgramState *state = Pred->getState();
-  SVal baseExprVal = state->getSVal(baseExpr);
+  const LocationContext *LCtx = Pred->getLocationContext();
+  SVal baseExprVal = state->getSVal(baseExpr, Pred->getLocationContext());
   if (isa<nonloc::LazyCompoundVal>(baseExprVal) ||
       isa<nonloc::CompoundVal>(baseExprVal) ||
       // FIXME: This can originate by conjuring a symbol for an unknown
       // temporary struct object, see test/Analysis/fields.c:
       // (p = getit()).x
       isa<nonloc::SymbolVal>(baseExprVal)) {
-    Bldr.generateNode(M, Pred, state->BindExpr(M, UnknownVal()));
+    Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, UnknownVal()));
     return;
   }
 
@@ -1354,7 +1378,7 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
   // For all other cases, compute an lvalue.    
   SVal L = state->getLValue(field, baseExprVal);
   if (M->isLValue())
-    Bldr.generateNode(M, Pred, state->BindExpr(M, L), false, 0,
+    Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, L), false, 0,
                       ProgramPoint::PostLValueKind);
   else {
     Bldr.takeNodes(Pred);
@@ -1465,7 +1489,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *Ex,
       // Perform the load from the referenced value.
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end() ; I!=E; ++I) {
         state = (*I)->getState();
-        location = state->getSVal(Ex);
+        location = state->getSVal(Ex, (*I)->getLocationContext());
         evalLoadCommon(Dst, Ex, *I, state, location, tag, LoadTy);
       }
       return;
@@ -1493,17 +1517,19 @@ void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst, const Expr *Ex,
   // Proceed with the load.
   for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
     state = (*NI)->getState();
+    const LocationContext *LCtx = (*NI)->getLocationContext();
 
     if (location.isUnknown()) {
       // This is important.  We must nuke the old binding.
-      Bldr.generateNode(Ex, *NI, state->BindExpr(Ex, UnknownVal()),
+      Bldr.generateNode(Ex, *NI, state->BindExpr(Ex, LCtx, UnknownVal()),
                         false, tag, ProgramPoint::PostLoadKind);
     }
     else {
       if (LoadTy.isNull())
         LoadTy = Ex->getType();
       SVal V = state->getSVal(cast<Loc>(location), LoadTy);
-      Bldr.generateNode(Ex, *NI, state->bindExprAndLocation(Ex, location, V),
+      Bldr.generateNode(Ex, *NI, state->bindExprAndLocation(Ex, LCtx,
+                                                            location, V),
                         false, tag, ProgramPoint::PostLoadKind);
     }
   }
@@ -1642,7 +1668,7 @@ void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
     }
 
     const ProgramState *state = Pred->getState();
-    SVal V = state->getSVal(Ex);
+    SVal V = state->getSVal(Ex, Pred->getLocationContext());
     nonloc::SymbolVal *SEV = dyn_cast<nonloc::SymbolVal>(&V);
     if (SEV && SEV->isExpression()) {
       const std::pair<const ProgramPointTag *, const ProgramPointTag*> &tags =
@@ -1651,14 +1677,14 @@ void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
       // First assume that the condition is true.
       if (const ProgramState *StateTrue = state->assume(*SEV, true)) {
         SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());        
-        StateTrue = StateTrue->BindExpr(Ex, Val);
+        StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);
         Bldr.generateNode(Ex, Pred, StateTrue, false, tags.first);
       }
 
       // Next, assume that the condition is false.
       if (const ProgramState *StateFalse = state->assume(*SEV, false)) {
         SVal Val = svalBuilder.makeIntVal(0U, Ex->getType());
-        StateFalse = StateFalse->BindExpr(Ex, Val);
+        StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);
         Bldr.generateNode(Ex, Pred, StateFalse, false, tags.second);
       }
     }
@@ -1706,7 +1732,7 @@ void ExprEngine::VisitAsmStmtHelperInputs(const AsmStmt *A,
     for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(),
                                    OE = A->end_outputs(); OI != OE; ++OI) {
 
-      SVal X = state->getSVal(*OI);
+      SVal X = state->getSVal(*OI, Pred->getLocationContext());
       assert (!isa<NonLoc>(X));  // Should be an Lval, or unknown, undef.
 
       if (isa<Loc>(X))
@@ -1911,7 +1937,7 @@ struct DOTGraphTraits<ExplodedNode*> :
     const ProgramState *state = N->getState();
     Out << "\\|StateID: " << (void*) state
         << " NodeID: " << (void*) N << "\\|";
-    state->printDOT(Out, *N->getLocationContext()->getCFG());
+    state->printDOT(Out);
 
     Out << "\\l";    
 
index 83bc39e1fdeb398eed3f568f9cd5cd36889f9c75..b3c5802079a5f8848b0e64123b5f6398a317fa02 100644 (file)
@@ -35,8 +35,9 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
          it != ei; ++it) {
       
     const ProgramState *state = (*it)->getState();
-    SVal LeftV = state->getSVal(LHS);
-    SVal RightV = state->getSVal(RHS);
+    const LocationContext *LCtx = (*it)->getLocationContext();
+    SVal LeftV = state->getSVal(LHS, LCtx);
+    SVal RightV = state->getSVal(RHS, LCtx);
       
     BinaryOperator::Opcode Op = B->getOpcode();
       
@@ -50,7 +51,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
       // Simulate the effects of a "store":  bind the value of the RHS
       // to the L-Value represented by the LHS.
       SVal ExprVal = B->isLValue() ? LeftV : RightV;
-      evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, ExprVal), LeftV, RightV);
+      evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, LCtx, ExprVal),
+                LeftV, RightV);
       continue;
     }
       
@@ -64,7 +66,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
         continue;
       }        
 
-      state = state->BindExpr(B, Result);      
+      state = state->BindExpr(B, LCtx, Result);      
       Bldr.generateNode(B, *it, state);
       continue;
     }
@@ -96,7 +98,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
          ++I) {
 
       state = (*I)->getState();
-      SVal V = state->getSVal(LHS);
+      const LocationContext *LCtx = (*I)->getLocationContext();
+      SVal V = state->getSVal(LHS, LCtx);
       
       // Get the computation type.
       QualType CTy =
@@ -143,9 +146,9 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
       // In C++, assignment and compound assignment operators return an 
       // lvalue.
       if (B->isLValue())
-        state = state->BindExpr(B, location);
+        state = state->BindExpr(B, LCtx, location);
       else
-        state = state->BindExpr(B, Result);
+        state = state->BindExpr(B, LCtx, Result);
       
       evalStore(Tmp2, B, LHS, *I, state, location, LHSVal);
     }
@@ -164,7 +167,10 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
   
   ExplodedNodeSet Tmp;
   StmtNodeBuilder Bldr(Pred, Tmp, *currentBuilderContext);
-  Bldr.generateNode(BE, Pred, Pred->getState()->BindExpr(BE, V), false, 0,
+  Bldr.generateNode(BE, Pred,
+                    Pred->getState()->BindExpr(BE, Pred->getLocationContext(),
+                                               V),
+                    false, 0,
                     ProgramPoint::PostLValueKind);
   
   // FIXME: Move all post/pre visits to ::Visit().
@@ -182,7 +188,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
          I!=E; ++I) {
       ExplodedNode *subExprNode = *I;
       const ProgramState *state = subExprNode->getState();
-      evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex));
+      const LocationContext *LCtx = subExprNode->getLocationContext();
+      evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex, LCtx));
     }
     return;
   }
@@ -216,8 +223,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
       case CK_FunctionToPointerDecay: {
         // Copy the SVal of Ex to CastE.
         const ProgramState *state = Pred->getState();
-        SVal V = state->getSVal(Ex);
-        state = state->BindExpr(CastE, V);
+        const LocationContext *LCtx = Pred->getLocationContext();
+        SVal V = state->getSVal(Ex, LCtx);
+        state = state->BindExpr(CastE, LCtx, V);
         Bldr.generateNode(CastE, Pred, state);
         continue;
       }
@@ -251,9 +259,10 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
       case CK_ObjCObjectLValueCast: {
         // Delegate to SValBuilder to process.
         const ProgramState *state = Pred->getState();
-        SVal V = state->getSVal(Ex);
+        const LocationContext *LCtx = Pred->getLocationContext();
+        SVal V = state->getSVal(Ex, LCtx);
         V = svalBuilder.evalCast(V, T, ExTy);
-        state = state->BindExpr(CastE, V);
+        state = state->BindExpr(CastE, LCtx, V);
         Bldr.generateNode(CastE, Pred, state);
         continue;
       }
@@ -261,9 +270,10 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
       case CK_UncheckedDerivedToBase: {
         // For DerivedToBase cast, delegate to the store manager.
         const ProgramState *state = Pred->getState();
-        SVal val = state->getSVal(Ex);
+        const LocationContext *LCtx = Pred->getLocationContext();
+        SVal val = state->getSVal(Ex, LCtx);
         val = getStoreManager().evalDerivedToBase(val, T);
-        state = state->BindExpr(CastE, val);
+        state = state->BindExpr(CastE, LCtx, val);
         Bldr.generateNode(CastE, Pred, state);
         continue;
       }
@@ -287,7 +297,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
         svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType,
                                currentBuilderContext->getCurrentBlockCount());
         
-        const ProgramState *state = Pred->getState()->BindExpr(CastE, result);
+        const LocationContext *LCtx = Pred->getLocationContext();
+        const ProgramState *state = Pred->getState()->BindExpr(CastE, LCtx,
+                                                               result);
         Bldr.generateNode(CastE, Pred, state);
         continue;
       }
@@ -304,14 +316,14 @@ void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
     = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
   
   const ProgramState *state = Pred->getState();
-  SVal ILV = state->getSVal(ILE);
+  SVal ILV = state->getSVal(ILE, Pred->getLocationContext());
   const LocationContext *LC = Pred->getLocationContext();
   state = state->bindCompoundLiteral(CL, LC, ILV);
   
   if (CL->isLValue())
-    B.generateNode(CL, Pred, state->BindExpr(CL, state->getLValue(CL, LC)));
+    B.generateNode(CL, Pred, state->BindExpr(CL, LC, state->getLValue(CL, LC)));
   else
-    B.generateNode(CL, Pred, state->BindExpr(CL, ILV));
+    B.generateNode(CL, Pred, state->BindExpr(CL, LC, ILV));
 }
 
 void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
@@ -345,7 +357,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
     const LocationContext *LC = N->getLocationContext();
     
     if (const Expr *InitEx = VD->getInit()) {
-      SVal InitVal = state->getSVal(InitEx);
+      SVal InitVal = state->getSVal(InitEx, Pred->getLocationContext());
       
       // We bound the temp obj region to the CXXConstructExpr. Now recover
       // the lazy compound value when the variable is not a reference.
@@ -379,18 +391,19 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
 
   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
   const ProgramState *state = Pred->getState();
-  SVal X = state->getSVal(B);
+  const LocationContext *LCtx = Pred->getLocationContext();
+  SVal X = state->getSVal(B, LCtx);
   assert(X.isUndef());
   
   const Expr *Ex = (const Expr*) cast<UndefinedVal>(X).getData();
   assert(Ex);
   
   if (Ex == B->getRHS()) {
-    X = state->getSVal(Ex);
+    X = state->getSVal(Ex, LCtx);
     
     // Handle undefined values.
     if (X.isUndef()) {
-      Bldr.generateNode(B, Pred, state->BindExpr(B, X));
+      Bldr.generateNode(B, Pred, state->BindExpr(B, LCtx, X));
       return;
     }
     
@@ -404,11 +417,13 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
     // the payoff is not likely to be large.  Instead, we do eager evaluation.
     if (const ProgramState *newState = state->assume(XD, true))
       Bldr.generateNode(B, Pred,
-               newState->BindExpr(B, svalBuilder.makeIntVal(1U, B->getType())));
+               newState->BindExpr(B, LCtx,
+                                  svalBuilder.makeIntVal(1U, B->getType())));
     
     if (const ProgramState *newState = state->assume(XD, false))
       Bldr.generateNode(B, Pred,
-               newState->BindExpr(B, svalBuilder.makeIntVal(0U, B->getType())));
+               newState->BindExpr(B, LCtx,
+                                  svalBuilder.makeIntVal(0U, B->getType())));
   }
   else {
     // We took the LHS expression.  Depending on whether we are '&&' or
@@ -416,7 +431,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
     // the short-circuiting.
     X = svalBuilder.makeIntVal(B->getOpcode() == BO_LAnd ? 0U : 1U,
                                B->getType());
-    Bldr.generateNode(B, Pred, state->BindExpr(B, X));
+    Bldr.generateNode(B, Pred, state->BindExpr(B, LCtx, X));
   }
 }
 
@@ -426,6 +441,7 @@ void ExprEngine::VisitInitListExpr(const InitListExpr *IE,
   StmtNodeBuilder B(Pred, Dst, *currentBuilderContext);
 
   const ProgramState *state = Pred->getState();
+  const LocationContext *LCtx = Pred->getLocationContext();
   QualType T = getContext().getCanonicalType(IE->getType());
   unsigned NumInitElements = IE->getNumInits();
   
@@ -436,24 +452,27 @@ void ExprEngine::VisitInitListExpr(const InitListExpr *IE,
     // e.g: static int* myArray[] = {};
     if (NumInitElements == 0) {
       SVal V = svalBuilder.makeCompoundVal(T, vals);
-      B.generateNode(IE, Pred, state->BindExpr(IE, V));
+      B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V));
       return;
     }
     
     for (InitListExpr::const_reverse_iterator it = IE->rbegin(),
          ei = IE->rend(); it != ei; ++it) {
-      vals = getBasicVals().consVals(state->getSVal(cast<Expr>(*it)), vals);
+      vals = getBasicVals().consVals(state->getSVal(cast<Expr>(*it), LCtx),
+                                     vals);
     }
     
     B.generateNode(IE, Pred,
-                   state->BindExpr(IE, svalBuilder.makeCompoundVal(T, vals)));
+                   state->BindExpr(IE, LCtx,
+                                   svalBuilder.makeCompoundVal(T, vals)));
     return;
   }
   
   if (Loc::isLocType(T) || T->isIntegerType()) {
     assert(IE->getNumInits() == 1);
     const Expr *initEx = IE->getInit(0);
-    B.generateNode(IE, Pred, state->BindExpr(IE, state->getSVal(initEx)));
+    B.generateNode(IE, Pred, state->BindExpr(IE, LCtx,
+                                             state->getSVal(initEx, LCtx)));
     return;
   }
   
@@ -468,14 +487,15 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
   StmtNodeBuilder B(Pred, Dst, *currentBuilderContext);
   
   const ProgramState *state = Pred->getState();
-  SVal X = state->getSVal(Ex);  
+  const LocationContext *LCtx = Pred->getLocationContext();
+  SVal X = state->getSVal(Ex, LCtx);  
   assert (X.isUndef());  
   const Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
   assert(SE);
-  X = state->getSVal(SE);
+  X = state->getSVal(SE, LCtx);
   
   // Make sure that we invalidate the previous binding.
-  B.generateNode(Ex, Pred, state->BindExpr(Ex, X, true));
+  B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, X, true));
 }
 
 void ExprEngine::
@@ -488,7 +508,9 @@ VisitOffsetOfExpr(const OffsetOfExpr *OOE,
     assert(OOE->getType()->isIntegerType());
     assert(IV.isSigned() == OOE->getType()->isSignedIntegerOrEnumerationType());
     SVal X = svalBuilder.makeIntVal(IV);
-    B.generateNode(OOE, Pred, Pred->getState()->BindExpr(OOE, X));
+    B.generateNode(OOE, Pred,
+                   Pred->getState()->BindExpr(OOE, Pred->getLocationContext(),
+                                              X));
   }
   // FIXME: Handle the case where __builtin_offsetof is not a constant.
 }
@@ -522,7 +544,8 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
   CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue());
   
   const ProgramState *state = Pred->getState();
-  state = state->BindExpr(Ex, svalBuilder.makeIntVal(amt.getQuantity(),
+  state = state->BindExpr(Ex, Pred->getLocationContext(),
+                          svalBuilder.makeIntVal(amt.getQuantity(),
                                                      Ex->getType()));
   Bldr.generateNode(Ex, Pred, state);
 }
@@ -555,7 +578,9 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
         // For all other types, UO_Real is an identity operation.
         assert (U->getType() == Ex->getType());
         const ProgramState *state = (*I)->getState();
-        Bldr.generateNode(U, *I, state->BindExpr(U, state->getSVal(Ex)));
+        const LocationContext *LCtx = (*I)->getLocationContext();
+        Bldr.generateNode(U, *I, state->BindExpr(U, LCtx,
+                                                 state->getSVal(Ex, LCtx)));
       }
       
       break;
@@ -576,8 +601,9 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
         
         // For all other types, UO_Imag returns 0.
         const ProgramState *state = (*I)->getState();
+        const LocationContext *LCtx = (*I)->getLocationContext();
         SVal X = svalBuilder.makeZeroVal(Ex->getType());
-        Bldr.generateNode(U, *I, state->BindExpr(U, X));
+        Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, X));
       }
       
       break;
@@ -601,7 +627,9 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
       
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
         const ProgramState *state = (*I)->getState();
-        Bldr.generateNode(U, *I, state->BindExpr(U, state->getSVal(Ex)));
+        const LocationContext *LCtx = (*I)->getLocationContext();
+        Bldr.generateNode(U, *I, state->BindExpr(U, LCtx,
+                                                 state->getSVal(Ex, LCtx)));
       }
       
       break;
@@ -617,12 +645,13 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
       
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
         const ProgramState *state = (*I)->getState();
+        const LocationContext *LCtx = (*I)->getLocationContext();
         
         // Get the value of the subexpression.
-        SVal V = state->getSVal(Ex);
+        SVal V = state->getSVal(Ex, LCtx);
         
         if (V.isUnknownOrUndef()) {
-          Bldr.generateNode(U, *I, state->BindExpr(U, V));
+          Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V));
           continue;
         }
         
@@ -632,12 +661,12 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
             
           case UO_Not:
             // FIXME: Do we need to handle promotions?
-            state = state->BindExpr(U, evalComplement(cast<NonLoc>(V)));
+            state = state->BindExpr(U, LCtx, evalComplement(cast<NonLoc>(V)));
             break;
             
           case UO_Minus:
             // FIXME: Do we need to handle promotions?
-            state = state->BindExpr(U, evalMinus(cast<NonLoc>(V)));
+            state = state->BindExpr(U, LCtx, evalMinus(cast<NonLoc>(V)));
             break;
             
           case UO_LNot:
@@ -659,7 +688,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
                                  U->getType());
             }
             
-            state = state->BindExpr(U, Result);
+            state = state->BindExpr(U, LCtx, Result);
             
             break;
         }
@@ -681,9 +710,9 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
   Visit(Ex, Pred, Tmp);
   
   for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
-    
+    const LocationContext *LCtx = (*I)->getLocationContext();
     const ProgramState *state = (*I)->getState();
-    SVal loc = state->getSVal(Ex);
+    SVal loc = state->getSVal(Ex, LCtx);
     
     // Perform a load.
     ExplodedNodeSet Tmp2;
@@ -694,11 +723,12 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
     for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) {
       
       state = (*I2)->getState();
-      SVal V2_untested = state->getSVal(Ex);
+      assert(LCtx == (*I2)->getLocationContext());
+      SVal V2_untested = state->getSVal(Ex, LCtx);
       
       // Propagate unknown and undefined values.
       if (V2_untested.isUnknownOrUndef()) {
-        Bldr.generateNode(U, *I2, state->BindExpr(U, V2_untested));
+        Bldr.generateNode(U, *I2, state->BindExpr(U, LCtx, V2_untested));
         continue;
       }
       DefinedSVal V2 = cast<DefinedSVal>(V2_untested);
@@ -749,9 +779,9 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
       // Since the lvalue-to-rvalue conversion is explicit in the AST,
       // we bind an l-value if the operator is prefix and an lvalue (in C++).
       if (U->isLValue())
-        state = state->BindExpr(U, loc);
+        state = state->BindExpr(U, LCtx, loc);
       else
-        state = state->BindExpr(U, U->isPostfix() ? V2 : Result);
+        state = state->BindExpr(U, LCtx, U->isPostfix() ? V2 : Result);
       
       // Perform the store.
       Bldr.takeNodes(*I2);
index 99752e5408dc103ef49a2817d5266cbb951918ca..f9e18fbc4a3627a2d77416c83ba0f921572278fd 100644 (file)
@@ -110,17 +110,17 @@ void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
   const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
   const ProgramState *state = Pred->getState();
+  const LocationContext *LCtx = Pred->getLocationContext();
 
   // Bind the temporary object to the value of the expression. Then bind
   // the expression to the location of the object.
-  SVal V = state->getSVal(tempExpr);
+  SVal V = state->getSVal(tempExpr, Pred->getLocationContext());
 
   const MemRegion *R =
-    svalBuilder.getRegionManager().getCXXTempObjectRegion(ME,
-                                                 Pred->getLocationContext());
+    svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx);
 
   state = state->bindLoc(loc::MemRegionVal(R), V);
-  Bldr.generateNode(ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R)));
+  Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R)));
 }
 
 void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 
@@ -208,7 +208,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
       const LocationContext *LC = Pred->getLocationContext();
       const ProgramState *state = Pred->getState();
 
-      state = invalidateArguments(state, CallOrObjCMessage(E, state), LC);
+      state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC);
       Bldr.generateNode(E, Pred, state);
     }
   }
@@ -256,7 +256,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
     // FIXME: allocating an array requires simulating the constructors.
     // For now, just return a symbolicated region.
     const ProgramState *state = Pred->getState();
-    state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
+    state = state->BindExpr(CNE, Pred->getLocationContext(),
+                            loc::MemRegionVal(EleReg));
     Bldr.generateNode(CNE, Pred, state);
     return;
   }
@@ -286,7 +287,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
           ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
           ai != ae; ++ai)
     {
-      SVal val = state->getSVal(*ai);
+      SVal val = state->getSVal(*ai, (*I)->getLocationContext());
       if (const MemRegion *region = val.getAsRegion())
         regionsToInvalidate.push_back(region);
     }
@@ -307,7 +308,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
                                        CNE, blockCount, 0, 0);
 
       if (CNE->hasInitializer()) {
-        SVal V = state->getSVal(*CNE->constructor_arg_begin());
+        SVal V = state->getSVal(*CNE->constructor_arg_begin(),
+                                (*I)->getLocationContext());
         state = state->bindLoc(loc::MemRegionVal(EleReg), V);
       } else {
         // Explicitly set to undefined, because currently we retrieve symbolic
@@ -315,7 +317,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
         state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal());
       }
     }
-    state = state->BindExpr(CNE, loc::MemRegionVal(EleReg));
+    state = state->BindExpr(CNE, (*I)->getLocationContext(),
+                            loc::MemRegionVal(EleReg));
     Bldr.generateNode(CNE, *I, state);
   }
 }
@@ -338,12 +341,13 @@ void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
   StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
 
   // Get the this object region from StoreManager.
+  const LocationContext *LCtx = Pred->getLocationContext();
   const MemRegion *R =
     svalBuilder.getRegionManager().getCXXThisRegion(
                                   getContext().getCanonicalType(TE->getType()),
-                                               Pred->getLocationContext());
+                                                    LCtx);
 
   const ProgramState *state = Pred->getState();
   SVal V = state->getSVal(loc::MemRegionVal(R));
-  Bldr.generateNode(TE, Pred, state->BindExpr(TE, V));
+  Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V));
 }
index faffee75fb2d051170869e36d09a64a7d7eedbd4..3b508d2899443999e8cfc912841c85868f12401e 100644 (file)
@@ -44,8 +44,9 @@ void ExprEngine::processCallExit(CallExitNodeBuilder &B) {
   // If the callee returns an expression, bind its value to CallExpr.
   const Stmt *ReturnedExpr = state->get<ReturnExpr>();
   if (ReturnedExpr) {
-    SVal RetVal = state->getSVal(ReturnedExpr);
-    state = state->BindExpr(CE, RetVal);
+    const LocationContext *LCtx = Pred->getLocationContext();
+    SVal RetVal = state->getSVal(ReturnedExpr, LCtx);
+    state = state->BindExpr(CE, LCtx, RetVal);
     // Clear the return expr GDM.
     state = state->remove<ReturnExpr>();
   }
@@ -57,7 +58,7 @@ void ExprEngine::processCallExit(CallExitNodeBuilder &B) {
     
     SVal ThisV = state->getSVal(ThisR);
     // Always bind the region to the CXXConstructExpr.
-    state = state->BindExpr(CCE, ThisV);
+    state = state->BindExpr(CCE, Pred->getLocationContext(), ThisV);
   }
   
   B.generateNode(state);
@@ -231,7 +232,7 @@ void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
       // Get the callee.
       const Expr *Callee = CE->getCallee()->IgnoreParens();
       const ProgramState *state = Pred->getState();
-      SVal L = state->getSVal(Callee);
+      SVal L = state->getSVal(Callee, Pred->getLocationContext());
 
       // Figure out the result type. We do this dance to handle references.
       QualType ResultTy;
@@ -249,11 +250,12 @@ void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
       SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count);
 
       // Generate a new state with the return value set.
-      state = state->BindExpr(CE, RetVal);
+      const LocationContext *LCtx = Pred->getLocationContext();
+      state = state->BindExpr(CE, LCtx, RetVal);
 
       // Invalidate the arguments.
-      const LocationContext *LC = Pred->getLocationContext();
-      state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state), LC);
+      state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state, LCtx),
+                                      LCtx);
 
       // And make the result node.
       Bldr.generateNode(CE, Pred, state);
index a03a7b29e60e71f8def4e1a47be55b5ea1f92c91..cb83d2f56091b9dcc99f6e6c4f9d27f74e4a316b 100644 (file)
@@ -22,12 +22,13 @@ void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex,
                                           ExplodedNode *Pred,
                                           ExplodedNodeSet &Dst) {
   const ProgramState *state = Pred->getState();
-  SVal baseVal = state->getSVal(Ex->getBase());
+  const LocationContext *LCtx = Pred->getLocationContext();
+  SVal baseVal = state->getSVal(Ex->getBase(), LCtx);
   SVal location = state->getLValue(Ex->getDecl(), baseVal);
   
   ExplodedNodeSet dstIvar;
   StmtNodeBuilder Bldr(Pred, dstIvar, *currentBuilderContext);
-  Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, location));
+  Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, location));
   
   // Perform the post-condition check of the ObjCIvarRefExpr and store
   // the created nodes in 'Dst'.
@@ -80,7 +81,7 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
     elementV = state->getLValue(elemD, Pred->getLocationContext());
   }
   else {
-    elementV = state->getSVal(elem);
+    elementV = state->getSVal(elem, Pred->getLocationContext());
   }
   
   ExplodedNodeSet dstLocation;
@@ -92,14 +93,15 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
        NE = dstLocation.end(); NI!=NE; ++NI) {
     Pred = *NI;
     const ProgramState *state = Pred->getState();
+    const LocationContext *LCtx = Pred->getLocationContext();
     
     // Handle the case where the container still has elements.
     SVal TrueV = svalBuilder.makeTruthVal(1);
-    const ProgramState *hasElems = state->BindExpr(S, TrueV);
+    const ProgramState *hasElems = state->BindExpr(S, LCtx, TrueV);
     
     // Handle the case where the container has no elements.
     SVal FalseV = svalBuilder.makeTruthVal(0);
-    const ProgramState *noElems = state->BindExpr(S, FalseV);
+    const ProgramState *noElems = state->BindExpr(S, LCtx, FalseV);
     
     if (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV))
       if (const TypedValueRegion *R = 
@@ -146,7 +148,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg,
     
     if (const Expr *Receiver = msg.getInstanceReceiver()) {
       const ProgramState *state = Pred->getState();
-      SVal recVal = state->getSVal(Receiver);
+      SVal recVal = state->getSVal(Receiver, Pred->getLocationContext());
       if (!recVal.isUndef()) {
         // Bifurcate the state into nil and non-nil ones.
         DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
@@ -241,7 +243,7 @@ void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr,
     // These methods return their receivers.
     const Expr *ReceiverE = msg.getInstanceReceiver();
     if (ReceiverE)
-      ReturnValue = state->getSVal(ReceiverE);
+      ReturnValue = state->getSVal(ReceiverE, Pred->getLocationContext());
     break;
   }
   }
@@ -256,11 +258,11 @@ void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr,
   }
 
   // Bind the return value.
-  state = state->BindExpr(currentStmt, ReturnValue);
+  const LocationContext *LCtx = Pred->getLocationContext();
+  state = state->BindExpr(currentStmt, LCtx, ReturnValue);
 
   // Invalidate the arguments (and the receiver)
-  const LocationContext *LC = Pred->getLocationContext();
-  state = invalidateArguments(state, CallOrObjCMessage(msg, state), LC);
+  state = invalidateArguments(state, CallOrObjCMessage(msg, state, LCtx), LCtx);
 
   // And create the new node.
   Bldr.generateNode(msg.getOriginExpr(), Pred, state, GenSink);
index 1edc3769e7a2c82a605cf9e476af198e1002b4f0..ac571a5ef676a7a21517b8121d943b0fdbcf15ae 100644 (file)
@@ -125,7 +125,7 @@ QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const {
 
     isLVal = FunctionCall->isLValue();
     const Expr *Callee = FunctionCall->getCallee();
-    if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl())
+    if (const FunctionDecl *FD = State->getSVal(Callee, LCtx).getAsFunctionDecl())
       resultTy = FD->getResultType();
     else
       resultTy = FunctionCall->getType();
@@ -141,7 +141,7 @@ SVal CallOrObjCMessage::getFunctionCallee() const {
   assert(isFunctionCall());
   assert(!isCXXCall());
   const Expr *Fun = CallE.get<const CallExpr *>()->getCallee()->IgnoreParens();
-  return State->getSVal(Fun);
+  return State->getSVal(Fun, LCtx);
 }
 
 SVal CallOrObjCMessage::getCXXCallee() const {
@@ -155,7 +155,7 @@ SVal CallOrObjCMessage::getCXXCallee() const {
   if (!callee)
     return UnknownVal();
   
-  return State->getSVal(callee);
+  return State->getSVal(callee, LCtx);
 }
 
 SVal
index 4b98ce8b0f78c6e08de40578348a0870f203d8ce..8a287e9e1699d04e840265cc6596cd8f822b561a 100644 (file)
@@ -239,9 +239,12 @@ SVal ProgramState::getSVal(Loc location, QualType T) const {
   return V;
 }
 
-const ProgramState *ProgramState::BindExpr(const Stmt *S, SVal V, bool Invalidate) const{
-  Environment NewEnv = getStateManager().EnvMgr.bindExpr(Env, S, V,
-                                                         Invalidate);
+const ProgramState *ProgramState::BindExpr(const Stmt *S,
+                                           const LocationContext *LCtx,
+                                           SVal V, bool Invalidate) const{
+  Environment NewEnv =
+    getStateManager().EnvMgr.bindExpr(Env, EnvironmentEntry(S, LCtx), V,
+                                      Invalidate);
   if (NewEnv == Env)
     return this;
 
@@ -250,10 +253,14 @@ const ProgramState *ProgramState::BindExpr(const Stmt *S, SVal V, bool Invalidat
   return getStateManager().getPersistentState(NewSt);
 }
 
-const ProgramState *ProgramState::bindExprAndLocation(const Stmt *S, SVal location,
-                                            SVal V) const {
+const ProgramState *
+ProgramState::bindExprAndLocation(const Stmt *S, const LocationContext *LCtx,
+                                  SVal location,
+                                  SVal V) const {
   Environment NewEnv =
-    getStateManager().EnvMgr.bindExprAndLocation(Env, S, location, V);
+    getStateManager().EnvMgr.bindExprAndLocation(Env,
+                                                 EnvironmentEntry(S, LCtx),
+                                                 location, V);
 
   if (NewEnv == Env)
     return this;
@@ -380,114 +387,28 @@ void ProgramState::setStore(const StoreRef &newStore) {
 //  State pretty-printing.
 //===----------------------------------------------------------------------===//
 
-static bool IsEnvLoc(const Stmt *S) {
-  // FIXME: This is a layering violation.  Should be in environment.
-  return (bool) (((uintptr_t) S) & 0x1);
-}
-
-void ProgramState::print(raw_ostream &Out, CFG *C,
+void ProgramState::print(raw_ostream &Out,
                          const char *NL, const char *Sep) const {
   // Print the store.
   ProgramStateManager &Mgr = getStateManager();
   Mgr.getStoreManager().print(getStore(), Out, NL, Sep);
-  bool isFirst = true;
-
-  // FIXME: All environment printing should be moved inside Environment.
-  if (C) {
-    // Print Subexpression bindings.
-    for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
-      if (C->isBlkExpr(I.getKey()) || IsEnvLoc(I.getKey()))
-        continue;
-
-      if (isFirst) {
-        Out << NL << NL << "Sub-Expressions:" << NL;
-        isFirst = false;
-      } else {
-        Out << NL;
-      }
 
-      Out << " (" << (void*) I.getKey() << ") ";
-      LangOptions LO; // FIXME.
-      I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
-      Out << " : " << I.getData();
-    }
-
-    // Print block-expression bindings.
-    isFirst = true;
-    for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
-      if (!C->isBlkExpr(I.getKey()))
-        continue;
-
-      if (isFirst) {
-        Out << NL << NL << "Block-level Expressions:" << NL;
-        isFirst = false;
-      } else {
-        Out << NL;
-      }
-
-      Out << " (" << (void*) I.getKey() << ") ";
-      LangOptions LO; // FIXME.
-      I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
-      Out << " : " << I.getData();
-    }
-  } else {
-    // Print All bindings - no info to differentiate block from subexpressions.
-    for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
-      if (IsEnvLoc(I.getKey()))
-        continue;
-
-      if (isFirst) {
-        Out << NL << NL << "Expressions:" << NL;
-        isFirst = false;
-      } else {
-        Out << NL;
-      }
-
-      Out << " (" << (void*) I.getKey() << ") ";
-      LangOptions LO; // FIXME.
-      I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
-      Out << " : " << I.getData();
-    }
-  }
-
-  // Print locations.
-  isFirst = true;
-  
-  for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
-    if (!IsEnvLoc(I.getKey()))
-      continue;
-    
-    if (isFirst) {
-      Out << NL << NL << "Load/store locations:" << NL;
-      isFirst = false;
-    } else {
-      Out << NL;
-    }
-
-    const Stmt *S = (Stmt*) (((uintptr_t) I.getKey()) & ((uintptr_t) ~0x1));
-    
-    Out << " (" << (void*) S << ") ";
-    LangOptions LO; // FIXME.
-    S->printPretty(Out, 0, PrintingPolicy(LO));
-    Out << " : " << I.getData();
-  }
+  // Print out the environment.
+  Env.print(Out, NL, Sep);
 
+  // Print out the constraints.
   Mgr.getConstraintManager().print(this, Out, NL, Sep);
 
   // Print checker-specific data.
   Mgr.getOwningEngine()->printState(Out, this, NL, Sep);
 }
 
-void ProgramState::printDOT(raw_ostream &Out, CFG &C) const {
-  print(Out, &C, "\\l", "\\|");
-}
-
-void ProgramState::dump(CFG &C) const {
-  print(llvm::errs(), &C);
+void ProgramState::printDOT(raw_ostream &Out) const {
+  print(Out, "\\l", "\\|");
 }
 
 void ProgramState::dump() const {
-  print(llvm::errs(), 0);
+  print(llvm::errs());
 }
 
 //===----------------------------------------------------------------------===//
@@ -654,15 +575,16 @@ bool ProgramState::scanReachableSymbols(const MemRegion * const *I,
 }
 
 const ProgramState* ProgramState::addTaint(const Stmt *S,
+                                           const LocationContext *LCtx,
                                            TaintTagType Kind) const {
   if (const Expr *E = dyn_cast_or_null<Expr>(S))
     S = E->IgnoreParens();
 
-  SymbolRef Sym = getSVal(S).getAsSymbol();
+  SymbolRef Sym = getSVal(S, LCtx).getAsSymbol();
   if (Sym)
     return addTaint(Sym, Kind);
 
-  const MemRegion *R = getSVal(S).getAsRegion();
+  const MemRegion *R = getSVal(S, LCtx).getAsRegion();
   addTaint(R, Kind);
 
   // Cannot add taint, so just return the state.
@@ -683,11 +605,12 @@ const ProgramState* ProgramState::addTaint(SymbolRef Sym,
   return NewState;
 }
 
-bool ProgramState::isTainted(const Stmt *S, TaintTagType Kind) const {
+bool ProgramState::isTainted(const Stmt *S, const LocationContext *LCtx,
+                             TaintTagType Kind) const {
   if (const Expr *E = dyn_cast_or_null<Expr>(S))
     S = E->IgnoreParens();
 
-  SVal val = getSVal(S);
+  SVal val = getSVal(S, LCtx);
   return isTainted(val, Kind);
 }
 
index a0d1bada247cce5a549d4d137143eaba7234e5b8..fa4ff044493517f16d1ea6fdfdf52d6e6de74e4c 100644 (file)
@@ -1863,7 +1863,7 @@ StoreRef RegionStoreManager::enterStackFrame(const ProgramState *state,
     // 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);
+      SVal ArgVal = state->getSVal(*AI, frame);
       store = Bind(store.getStore(),
                    svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, frame)), ArgVal);
     }
@@ -1874,7 +1874,7 @@ StoreRef RegionStoreManager::enterStackFrame(const ProgramState *state,
 
     // Copy the arg expression value to the arg variables.
     for (; AI != AE; ++AI, ++PI) {
-      SVal ArgVal = state->getSVal(*AI);
+      SVal ArgVal = state->getSVal(*AI, frame);
       store = Bind(store.getStore(),
                    svalBuilder.makeLoc(MRMgr.getVarRegion(*PI,frame)), ArgVal);
     }
index d31dd06092dbd917410b9726c9466ee5f57b0b80..bdb9ea74c215576e062a38391cd6bc9b148f4fe0 100644 (file)
@@ -491,7 +491,16 @@ bool SymbolReaper::isLive(SymbolRef sym) {
   return isa<SymbolRegionValue>(sym);
 }
 
-bool SymbolReaper::isLive(const Stmt *ExprVal) const {
+bool
+SymbolReaper::isLive(const Stmt *ExprVal, const LocationContext *ELCtx) const {
+  if (LCtx != ELCtx) {
+    // If the reaper's location context is a parent of the expression's
+    // location context, then the expression value is now "out of scope".
+    if (LCtx->isParentOf(ELCtx))
+      return false;
+    return true;
+  }
+
   return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal);
 }