From 632e3b7ee23f75016795e7ee43422aeda42ba1a8 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Fri, 6 Jan 2012 22:09:28 +0000 Subject: [PATCH] [analyzer] Make the entries in 'Environment' context-sensitive by making entries map from (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). llvm-svn: 147688 --- .../StaticAnalyzer/Core/PathSensitive/CoreEngine.h | 9 ++ .../Core/PathSensitive/Environment.h | 66 ++++++++--- .../StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 6 +- .../Core/PathSensitive/ObjCMessage.h | 28 +++-- .../Core/PathSensitive/ProgramState.h | 39 ++++--- .../Core/PathSensitive/SymbolManager.h | 2 +- .../Checkers/AdjustedReturnValueChecker.cpp | 9 +- .../StaticAnalyzer/Checkers/AttrNonNullChecker.cpp | 5 +- .../Checkers/BasicObjCFoundationChecks.cpp | 12 +- .../Checkers/BuiltinFunctionChecker.cpp | 9 +- .../lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 85 ++++++++------ .../Checkers/CallAndMessageChecker.cpp | 16 ++- .../StaticAnalyzer/Checkers/CastSizeChecker.cpp | 2 +- .../lib/StaticAnalyzer/Checkers/ChrootChecker.cpp | 2 +- .../lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp | 2 +- .../Checkers/FixedAddressChecker.cpp | 3 +- .../Checkers/GenericTaintChecker.cpp | 16 +-- .../Checkers/IdempotentOperationChecker.cpp | 6 +- .../StaticAnalyzer/Checkers/IteratorsChecker.cpp | 4 +- .../Checkers/MacOSKeychainAPIChecker.cpp | 10 +- .../StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp | 3 +- .../lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 24 ++-- .../Checkers/NoReturnFunctionChecker.cpp | 2 +- .../StaticAnalyzer/Checkers/OSAtomicChecker.cpp | 23 ++-- .../StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp | 2 +- .../Checkers/ObjCSelfInitChecker.cpp | 11 +- .../Checkers/PointerArithChecker.cpp | 5 +- .../StaticAnalyzer/Checkers/PointerSubChecker.cpp | 5 +- .../StaticAnalyzer/Checkers/PthreadLockChecker.cpp | 17 ++- .../StaticAnalyzer/Checkers/RetainCountChecker.cpp | 41 ++++--- .../Checkers/ReturnPointerRangeChecker.cpp | 2 +- .../StaticAnalyzer/Checkers/ReturnUndefChecker.cpp | 2 +- .../Checkers/StackAddrEscapeChecker.cpp | 2 +- .../lib/StaticAnalyzer/Checkers/StreamChecker.cpp | 42 ++++--- .../StaticAnalyzer/Checkers/TaintTesterChecker.cpp | 2 +- .../StaticAnalyzer/Checkers/UndefBranchChecker.cpp | 12 +- .../Checkers/UndefCapturedBlockVarChecker.cpp | 3 +- .../StaticAnalyzer/Checkers/UndefResultChecker.cpp | 7 +- .../Checkers/UndefinedArraySubscriptChecker.cpp | 2 +- .../Checkers/UndefinedAssignmentChecker.cpp | 2 +- .../lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp | 11 +- .../lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp | 2 +- clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 2 +- .../StaticAnalyzer/Core/BugReporterVisitors.cpp | 6 +- clang/lib/StaticAnalyzer/Core/CheckerContext.cpp | 2 +- clang/lib/StaticAnalyzer/Core/Environment.cpp | 113 +++++++++++++----- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 104 ++++++++++------- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 128 ++++++++++++-------- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 26 +++-- .../Core/ExprEngineCallAndReturn.cpp | 16 +-- clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp | 22 ++-- clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp | 6 +- clang/lib/StaticAnalyzer/Core/ProgramState.cpp | 129 +++++---------------- clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 4 +- clang/lib/StaticAnalyzer/Core/SymbolManager.cpp | 11 +- 55 files changed, 648 insertions(+), 474 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 3a51182..875df3a 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -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 { diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h index 2463e23..c58da3e 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h @@ -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 { +public: + EnvironmentEntry(const Stmt *s, const LocationContext *L) + : std::pair(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 BindingsTy; + typedef llvm::ImmutableMap 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 diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 3877cb8..f6d4998 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -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. diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h index 500f587..bcaf259 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h @@ -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(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 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 { diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index e9d6d6e..c3396d4 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -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(S)) { QualType T = Ex->getType(); if (Ex->isLValue() || Loc::isLocType(T) || T->isIntegerType()) - return getSVal(S); + return getSVal(S, LCtx); } return UnknownVal(); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 32381e7..3690b11 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -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. diff --git a/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp index 7dad242..df5620b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp @@ -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)); } } diff --git a/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp index 8296eb9..a3dc964 100644 --- a/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp @@ -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(&V); // If the value is unknown or undefined, we can't perform this check. diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 1f62729..fbe4671 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -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(&ArgVal); if (!DefArgVal) return; @@ -593,7 +594,8 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg, continue; // Ignore pointer constants. - if (isa(msg.getArgSVal(I, state))) + if (isa(msg.getArgSVal(I, C.getLocationContext(), + state))) continue; // Ignore pointer types annotated with 'NSObject' attribute. diff --git a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index 2cf1209..50938fa 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -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(state->getSVal(*(CE->arg_begin()))); + cast(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; } } diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 49d8bf5..bc8d184 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -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(&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(&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(&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(state->getSVal(Left)); - DefinedOrUnknownSVal RV = cast(state->getSVal(Right)); + DefinedOrUnknownSVal LV = + cast(state->getSVal(Left, LCtx)); + DefinedOrUnknownSVal RV = + cast(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(&strLength); NonLoc *maxlenValNL = dyn_cast(&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(getCStringLength(C, state, Init, StrVal)); diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index 914b806..f5f0c16 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -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; } diff --git a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp index 84a9e6b..32b60d9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp @@ -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; diff --git a/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp index fa79f21..22f7b77 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp @@ -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(); diff --git a/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp index d4fbfa1..12fd6f4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp @@ -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(&Denom); // Divide-by-undefined handled in the generic checking for uses of diff --git a/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp index 7bdd4f3..d570da0 100644 --- a/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp @@ -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; diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp index f09d670..9e67e21 100644 --- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -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(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(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() == PrevisitTaintRet) { - State = State->addTaint(CE); + State = State->addTaint(CE, C.getLocationContext()); return State->set(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(); diff --git a/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp index a3ebf0b..ef830e8 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp @@ -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()) { diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp index ab3242b..341d425 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp @@ -254,7 +254,7 @@ const ProgramState *IteratorsChecker::handleAssign(const ProgramState *state, lexp = M->GetTemporaryExpr(); if (const ImplicitCastExpr *ICE = dyn_cast(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(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) diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp index 78707e7..0a675e5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp @@ -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(&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(getSymbolForRegion(C, V)); diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp index f8c0104..9141656 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp @@ -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(R->getMemorySpace())) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index dcc7ab9..ea42da4 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -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(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(state->getSVal(arg0Expr)); + = cast(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(state->getSVal(Arg1)); + cast(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; diff --git a/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp index 81f1924..b831a82 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp @@ -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; diff --git a/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp index 27d8fb5..4089b34 100644 --- a/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp @@ -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); } } diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp index 5db073c..06b138e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp @@ -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(V)) { diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index 8b29a20..a466b41 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -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(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(argV)), C); C.addTransition(state->set(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(); state = state->remove(); @@ -289,7 +290,7 @@ void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE, } else if (hasSelfFlag(argV, SelfFlag_Self, C)) { SelfFlagEnum prevFlags = (SelfFlagEnum)state->get(); state = state->remove(); - addSelfFlag(state, state->getSVal(CE), prevFlags, C); + addSelfFlag(state, state->getSVal(CE, LCtx), prevFlags, C); return; } } diff --git a/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp index 845ae4f..6adc4dc 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp @@ -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(); diff --git a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp index 5e5e3e3..51f57a2 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp @@ -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(); diff --git a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp index 45988f0..a3bbd25 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -57,6 +57,7 @@ template <> struct ProgramStateTrait : 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; diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 24df008..8ba1edb 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -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 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(Sym); if (!CurrT) return NULL; @@ -1860,7 +1861,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, if (const CallExpr *CE = dyn_cast(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(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(N->getLocation()).getStmt(); - SVal X = CurrSt->getSValAsScalarOrLoc(cast(S)->getCallee()); + SVal X = + CurrSt->getSValAsScalarOrLoc(cast(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(*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(state->getSVal(BE).getAsRegion()); + cast(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(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; diff --git a/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp index e761bff..f176eec 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp @@ -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(R); diff --git a/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp index e8c8d90..e1316b5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp @@ -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(); diff --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index 0d3059e..8eda407 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -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()) diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 2f96bbf..c746c77 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -223,7 +223,7 @@ void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const { SValBuilder &svalBuilder = C.getSValBuilder(); DefinedSVal RetVal = cast(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(&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; diff --git a/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp index 415346f..297beae 100644 --- a/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp @@ -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); diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp index afb79b5..fc0b9c2 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp @@ -28,8 +28,10 @@ class UndefBranchChecker : public Checker { 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 { 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. diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp index 82c9fd4..60f1f5b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp @@ -57,7 +57,8 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE, const ProgramState *state = C.getState(); const BlockDataRegion *R = - cast(state->getSVal(BE).getAsRegion()); + cast(state->getSVal(BE, + C.getLocationContext()).getAsRegion()); BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(), E = R->referenced_vars_end(); diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp index 7ae9668..b074ff9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp @@ -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; } diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp index bb6831b..ee58a04 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp @@ -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")); diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp index 5ca4a9f..bb9eeb1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp @@ -55,7 +55,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val, if (const BinaryOperator *B = dyn_cast(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(); diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index 28ff697..420acd5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -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(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(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; diff --git a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp index 969a896..0308bf5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -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. diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 8ef9c21..38be389 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -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; diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 88f38a3..b27595a 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -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(&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(V) || isa(V)) { // Register a new visitor with the BugReport. diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index 5552a99..3737ca5 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -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(); } diff --git a/clang/lib/StaticAnalyzer/Core/Environment.cpp b/clang/lib/StaticAnalyzer/Core/Environment.cpp index e1b982c..f43c2ad 100644 --- a/clang/lib/StaticAnalyzer/Core/Environment.cpp +++ b/clang/lib/StaticAnalyzer/Core/Environment.cpp @@ -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(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, 10> deferredLocations; + SmallVector, 10> deferredLocations; MarkLiveCallback CB(SymReaper); ScanReachableSymbols RSScaner(ST, CB); - llvm::ImmutableMapRef + llvm::ImmutableMapRef 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 >::iterator + for (SmallVectorImpl >::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(); + } +} diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index f7022c6..2ab501a 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -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(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(*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(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(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(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(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(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(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(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(baseExprVal) || isa(baseExprVal) || // FIXME: This can originate by conjuring a symbol for an unknown // temporary struct object, see test/Analysis/fields.c: // (p = getit()).x isa(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(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(&V); if (SEV && SEV->isExpression()) { const std::pair &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(X)); // Should be an Lval, or unknown, undef. if (isa(X)) @@ -1911,7 +1937,7 @@ struct DOTGraphTraits : const ProgramState *state = N->getState(); Out << "\\|StateID: " << (void*) state << " NodeID: " << (void*) N << "\\|"; - state->printDOT(Out, *N->getLocationContext()->getCFG()); + state->printDOT(Out); Out << "\\l"; diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 83bc39e..b3c5802 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -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(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(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(*it)), vals); + vals = getBasicVals().consVals(state->getSVal(cast(*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(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(V))); + state = state->BindExpr(U, LCtx, evalComplement(cast(V))); break; case UO_Minus: // FIXME: Do we need to handle promotions? - state = state->BindExpr(U, evalMinus(cast(V))); + state = state->BindExpr(U, LCtx, evalMinus(cast(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(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); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 99752e5..f9e18fb 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -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)); } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index faffee7..3b508d2 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -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(); 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(); } @@ -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); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp index a03a7b2..cb83d2f 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp @@ -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(&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(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); diff --git a/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp b/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp index 1edc376..ac571a5 100644 --- a/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp +++ b/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp @@ -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()->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 diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp index 4b98ce8..8a287e9 100644 --- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -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(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(S)) S = E->IgnoreParens(); - SVal val = getSVal(S); + SVal val = getSVal(S, LCtx); return isTainted(val, Kind); } diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index a0d1bad..fa4ff04 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -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); } diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp index d31dd06..bdb9ea7 100644 --- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -491,7 +491,16 @@ bool SymbolReaper::isLive(SymbolRef sym) { return isa(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()->isLive(Loc, ExprVal); } -- 2.7.4