Index: cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/Checker.h @@ -321,9 +321,11 @@ const InvalidatedSymbols *invalidated, ArrayRef Explicits, ArrayRef Regions, + const LocationContext *LCtx, const CallEvent *Call) { - return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, - Explicits, Regions, Call); + return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated, + Explicits, Regions, + LCtx, Call); } public: Index: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -338,6 +338,7 @@ const InvalidatedSymbols *invalidated, ArrayRef ExplicitRegions, ArrayRef Regions, + const LocationContext *LCtx, const CallEvent *Call); /// \brief Run checkers when pointers escape. @@ -443,10 +444,11 @@ typedef CheckerFn CheckLiveSymbolsFunc; typedef CheckerFn ExplicitRegions, - ArrayRef Regions, - const CallEvent *Call)> + const InvalidatedSymbols *symbols, + ArrayRef ExplicitRegions, + ArrayRef Regions, + const LocationContext *LCtx, + const CallEvent *Call)> CheckRegionChangesFunc; typedef CheckerFn ExplicitRegions, ArrayRef Regions, + const LocationContext *LCtx, const CallEvent *Call) override; /// printState - Called by ProgramStateManager to print checker-specific data. @@ -522,7 +523,9 @@ /// Call PointerEscape callback when a value escapes as a result of bind. ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, - SVal Loc, SVal Val) override; + SVal Loc, + SVal Val, + const LocationContext *LCtx) override; /// Call PointerEscape callback when a value escapes as a result of /// region invalidation. /// \param[in] ITraits Specifies invalidation traits for regions/symbols. Index: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -229,11 +229,12 @@ ProgramStateRef bindLoc(Loc location, SVal V, + const LocationContext *LCtx, bool notifyChanges = true) const; - ProgramStateRef bindLoc(SVal location, SVal V) const; + ProgramStateRef bindLoc(SVal location, SVal V, const LocationContext *LCtx) const; - ProgramStateRef bindDefault(SVal loc, SVal V) const; + ProgramStateRef bindDefault(SVal loc, SVal V, const LocationContext *LCtx) const; ProgramStateRef killBinding(Loc LV) const; @@ -681,9 +682,9 @@ this, Val.castAs(), From, To); } -inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const { +inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationContext *LCtx) const { if (Optional L = LV.getAs()) - return bindLoc(*L, V); + return bindLoc(*L, V, LCtx); return this; } Index: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -131,17 +131,19 @@ const InvalidatedSymbols *invalidated, ArrayRef ExplicitRegions, ArrayRef Regions, + const LocationContext *LCtx, const CallEvent *Call) = 0; inline ProgramStateRef processRegionChange(ProgramStateRef state, - const MemRegion* MR) { - return processRegionChanges(state, nullptr, MR, MR, nullptr); + const MemRegion* MR, + const LocationContext *LCtx) { + return processRegionChanges(state, nullptr, MR, MR, LCtx, nullptr); } virtual ProgramStateRef - processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val) = 0; + processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val, const LocationContext *LCtx) = 0; virtual ProgramStateRef notifyCheckersOfPointerEscape(ProgramStateRef State, Index: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -68,6 +68,7 @@ const InvalidatedSymbols *, ArrayRef ExplicitRegions, ArrayRef Regions, + const LocationContext *LCtx, const CallEvent *Call) const; typedef void (CStringChecker::*FnCheck)(CheckerContext &, @@ -1943,8 +1944,12 @@ // Overwrite the search string pointer. The new value is either an address // further along in the same string, or NULL if there are no more tokens. State = State->bindLoc(*SearchStrLoc, - SVB.conjureSymbolVal(getTag(), CE, LCtx, CharPtrTy, - C.blockCount())); + SVB.conjureSymbolVal(getTag(), + CE, + LCtx, + CharPtrTy, + C.blockCount()), + LCtx); } else { assert(SearchStrVal.isUnknown()); // Conjure a symbolic value. It's the best we can do. @@ -2116,6 +2121,7 @@ const InvalidatedSymbols *, ArrayRef ExplicitRegions, ArrayRef Regions, + const LocationContext *LCtx, const CallEvent *Call) const { CStringLengthTy Entries = state->get(); if (Entries.isEmpty()) Index: cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CXXSelfAssignmentChecker.cpp @@ -51,9 +51,9 @@ State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame())); auto Param = SVB.makeLoc(State->getRegion(MD->getParamDecl(0), LCtx)); auto ParamVal = State->getSVal(Param); - ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal); + ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal, LCtx); C.addTransition(SelfAssignState); - ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal); + ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal, LCtx); C.addTransition(NonSelfAssignState); } Index: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp @@ -231,14 +231,6 @@ /// check::LiveSymbols void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const {} - /// \brief Called to determine if the checker currently needs to know if when - /// contents of any regions change. - /// - /// Since it is not necessarily cheap to compute which regions are being - /// changed, this allows the analyzer core to skip the more expensive - /// #checkRegionChanges when no checkers are tracking any state. - bool wantsRegionChangeUpdate(ProgramStateRef St) const { return true; } - /// \brief Called when the contents of one or more regions change. /// /// This can occur in many different ways: an explicit bind, a blanket @@ -255,18 +247,18 @@ /// by this change. For a simple bind, this list will be the same as /// \p ExplicitRegions, since a bind does not affect the contents of /// anything accessible through the base region. + /// \param LCtx LocationContext that is useful for getting various contextual + /// info, like callstack, CFG etc. /// \param Call The opaque call triggering this invalidation. Will be 0 if the /// change was not triggered by a call. /// - /// Note that this callback will not be invoked unless - /// #wantsRegionChangeUpdate returns \c true. - /// /// check::RegionChanges ProgramStateRef checkRegionChanges(ProgramStateRef State, const InvalidatedSymbols *Invalidated, ArrayRef ExplicitRegions, ArrayRef Regions, + const LocationContext *LCtx, const CallEvent *Call) const { return State; } Index: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -1154,7 +1154,7 @@ State = State->BindExpr(CE, C.getLocationContext(), RetVal); // Fill the region with the initialization value. - State = State->bindDefault(RetVal, Init); + State = State->bindDefault(RetVal, Init, LCtx); // Set the region's extent equal to the Size parameter. const SymbolicRegion *R = Index: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -2661,6 +2661,7 @@ const InvalidatedSymbols *invalidated, ArrayRef ExplicitRegions, ArrayRef Regions, + const LocationContext* LCtx, const CallEvent *Call) const; void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const; @@ -3647,7 +3648,7 @@ // same state. SVal StoredVal = state->getSVal(regionLoc->getRegion()); if (StoredVal != val) - escapes = (state == (state->bindLoc(*regionLoc, val))); + escapes = (state == (state->bindLoc(*regionLoc, val, C.getLocationContext()))); } if (!escapes) { // Case 4: We do not currently model what happens when a symbol is @@ -3714,10 +3715,11 @@ ProgramStateRef RetainCountChecker::checkRegionChanges(ProgramStateRef state, - const InvalidatedSymbols *invalidated, - ArrayRef ExplicitRegions, - ArrayRef Regions, - const CallEvent *Call) const { + const InvalidatedSymbols *invalidated, + ArrayRef ExplicitRegions, + ArrayRef Regions, + const LocationContext *LCtx, + const CallEvent *Call) const { if (!invalidated) return state; Index: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -521,17 +521,19 @@ /// \brief Run checkers for region changes. ProgramStateRef CheckerManager::runCheckersForRegionChanges(ProgramStateRef state, - const InvalidatedSymbols *invalidated, - ArrayRef ExplicitRegions, - ArrayRef Regions, - const CallEvent *Call) { + const InvalidatedSymbols *invalidated, + ArrayRef ExplicitRegions, + ArrayRef Regions, + const LocationContext *LCtx, + const CallEvent *Call) { for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { // If any checker declares the state infeasible (or if it starts that way), // bail out. if (!state) return nullptr; state = RegionChangesCheckers[i](state, invalidated, - ExplicitRegions, Regions, Call); + ExplicitRegions, Regions, + LCtx, Call); } return state; } Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -254,7 +254,7 @@ break; case SubobjectAdjustment::MemberPointerAdjustment: // FIXME: Unimplemented. - State->bindDefault(Reg, UnknownVal()); + State->bindDefault(Reg, UnknownVal(), LC); return State; } } @@ -265,7 +265,7 @@ currBldrCtx->blockCount()); // Bind the value of the expression to the sub-object region, and then bind // the sub-object region to our expression. - State = State->bindLoc(Reg, V); + State = State->bindLoc(Reg, V, LC); State = State->BindExpr(Result, LC, Reg); return State; } @@ -286,9 +286,11 @@ const InvalidatedSymbols *invalidated, ArrayRef Explicits, ArrayRef Regions, + const LocationContext *LCtx, const CallEvent *Call) { return getCheckerManager().runCheckersForRegionChanges(state, invalidated, - Explicits, Regions, Call); + Explicits, Regions, + LCtx, Call); } void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State, @@ -2165,7 +2167,9 @@ // (3) We are binding to a MemRegion with stack storage that the store // does not understand. ProgramStateRef ExprEngine::processPointerEscapedOnBind(ProgramStateRef State, - SVal Loc, SVal Val) { + SVal Loc, + SVal Val, + const LocationContext *LCtx) { // Are we storing to something that causes the value to "escape"? bool escapes = true; @@ -2181,7 +2185,7 @@ // same state. SVal StoredVal = State->getSVal(regionLoc->getRegion()); if (StoredVal != Val) - escapes = (State == (State->bindLoc(*regionLoc, Val))); + escapes = (State == (State->bindLoc(*regionLoc, Val, LCtx))); } } @@ -2278,7 +2282,7 @@ const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr, /*tag*/nullptr); ProgramStateRef state = Pred->getState(); - state = processPointerEscapedOnBind(state, location, Val); + state = processPointerEscapedOnBind(state, location, Val, LC); Bldr.generateNode(L, state, Pred); return; } @@ -2288,13 +2292,13 @@ ExplodedNode *PredI = *I; ProgramStateRef state = PredI->getState(); - state = processPointerEscapedOnBind(state, location, Val); + state = processPointerEscapedOnBind(state, location, Val, LC); // When binding the value, pass on the hint that this is a initialization. // For initializations, we do not need to inform clients of region // changes. state = state->bindLoc(location.castAs(), - Val, /* notifyChanges = */ !atDeclInit); + Val, LC, /* notifyChanges = */ !atDeclInit); const MemRegion *LocReg = nullptr; if (Optional LocRegVal = @@ -2520,7 +2524,7 @@ assert (!X.getAs()); // Should be an Lval, or unknown, undef. if (Optional LV = X.getAs()) - state = state->bindLoc(*LV, UnknownVal()); + state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext()); } Bldr.generateNode(A, Pred, state); Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -227,12 +227,13 @@ if (capturedR != originalR) { SVal originalV; + const LocationContext *LCtx = Pred->getLocationContext(); if (copyExpr) { - originalV = State->getSVal(copyExpr, Pred->getLocationContext()); + originalV = State->getSVal(copyExpr, LCtx); } else { originalV = State->getSVal(loc::MemRegionVal(originalR)); } - State = State->bindLoc(loc::MemRegionVal(capturedR), originalV); + State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, LCtx); } } } @@ -534,7 +535,7 @@ } else { assert(isa(Init)); Loc CLLoc = State->getLValue(CL, LCtx); - State = State->bindLoc(CLLoc, V); + State = State->bindLoc(CLLoc, V, LCtx); if (CL->isGLValue()) V = CLLoc; Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -317,7 +317,7 @@ // actually make things worse. Placement new makes this tricky as well, // since it's then possible to be initializing one part of a multi- // dimensional array. - State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal); + State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal, LCtx); Bldr.generateNode(CE, *I, State, /*tag=*/nullptr, ProgramPoint::PreStmtKind); } @@ -572,7 +572,7 @@ SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(), currBldrCtx->blockCount()); ProgramStateRef state = Pred->getState(); - state = state->bindLoc(state->getLValue(VD, LCtx), V); + state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx); StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); Bldr.generateNode(CS, Pred, state); @@ -627,7 +627,7 @@ InitVal = State->getSVal(SizeExpr, LocCtxt); } - State = State->bindLoc(FieldLoc, InitVal); + State = State->bindLoc(FieldLoc, InitVal, LocCtxt); } // Decay the Loc into an RValue, because there might be a Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp @@ -115,11 +115,11 @@ SymbolRef Sym = SymMgr.conjureSymbol(elem, LCtx, T, currBldrCtx->blockCount()); SVal V = svalBuilder.makeLoc(Sym); - hasElems = hasElems->bindLoc(elementV, V); + hasElems = hasElems->bindLoc(elementV, V, LCtx); // Bind the location to 'nil' on the false branch. SVal nilV = svalBuilder.makeIntVal(0, T); - noElems = noElems->bindLoc(elementV, nilV); + noElems = noElems->bindLoc(elementV, nilV, LCtx); } // Create the new nodes. Index: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -111,24 +111,29 @@ return ConstraintMgr->removeDeadBindings(Result, SymReaper); } -ProgramStateRef ProgramState::bindLoc(Loc LV, SVal V, bool notifyChanges) const { +ProgramStateRef ProgramState::bindLoc(Loc LV, + SVal V, + const LocationContext *LCtx, + bool notifyChanges) const { ProgramStateManager &Mgr = getStateManager(); ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(), LV, V)); const MemRegion *MR = LV.getAsRegion(); if (MR && Mgr.getOwningEngine() && notifyChanges) - return Mgr.getOwningEngine()->processRegionChange(newState, MR); + return Mgr.getOwningEngine()->processRegionChange(newState, MR, LCtx); return newState; } -ProgramStateRef ProgramState::bindDefault(SVal loc, SVal V) const { +ProgramStateRef ProgramState::bindDefault(SVal loc, + SVal V, + const LocationContext *LCtx) const { ProgramStateManager &Mgr = getStateManager(); const MemRegion *R = loc.castAs().getRegion(); const StoreRef &newStore = Mgr.StoreMgr->BindDefault(getStore(), R, V); ProgramStateRef new_state = makeWithStore(newStore); return Mgr.getOwningEngine() ? - Mgr.getOwningEngine()->processRegionChange(new_state, R) : + Mgr.getOwningEngine()->processRegionChange(new_state, R, LCtx) : new_state; } @@ -202,7 +207,7 @@ } return Eng->processRegionChanges(newState, IS, TopLevelInvalidated, - Invalidated, Call); + Invalidated, LCtx, Call); } const StoreRef &newStore =