Index: clang/include/clang/StaticAnalyzer/Core/CheckerManager.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ clang/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -395,9 +395,12 @@ /// Run checkers for evaluating a call. /// /// Warning: Currently, the CallEvent MUST come from a CallExpr! - void runCheckersForEvalCall(ExplodedNodeSet &Dst, - const ExplodedNodeSet &Src, - const CallEvent &CE, ExprEngine &Eng); + void + runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, + const CallEvent &CE, ExprEngine &Eng, + InvalidatedSymbols *IS, + RegionAndSymbolInvalidationTraits *ETraits, + StoreManager::InvalidatedRegions *TopLevelInvalidated); /// Run checkers for the entire Translation Unit. void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -32,6 +32,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/PointerIntPair.h" @@ -344,8 +345,13 @@ /// /// This accepts an alternate state in case some processing has already /// occurred. - ProgramStateRef invalidateRegions(unsigned BlockCount, - ProgramStateRef Orig = nullptr) const; + /// + /// It can also return a list of symbols stored into escaped regions. + ProgramStateRef invalidateRegions( + unsigned BlockCount, ProgramStateRef Orig = nullptr, + InvalidatedSymbols *NewIS = nullptr, + RegionAndSymbolInvalidationTraits *ETraits = nullptr, + StoreManager::InvalidatedRegions *TopLevelInvalidated = nullptr) const; using FrameBindingTy = std::pair; using BindingsTy = SmallVectorImpl; Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -31,6 +31,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" #include "llvm/ADT/ArrayRef.h" @@ -672,9 +673,11 @@ const CallEvent &Call); /// Default implementation of call evaluation. - void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, - const CallEvent &Call, - const EvalCallOptions &CallOpts = {}); + void defaultEvalCall( + NodeBuilder &B, ExplodedNode *Pred, const CallEvent &Call, + const EvalCallOptions &CallOpts = {}, InvalidatedSymbols *IS = nullptr, + RegionAndSymbolInvalidationTraits *ETraits = nullptr, + StoreManager::InvalidatedRegions *TopLevelInvalidated = nullptr); private: ProgramStateRef finishArgumentConstruction(ProgramStateRef State, @@ -745,14 +748,19 @@ /// Conservatively evaluate call by invalidating regions and binding /// a conjured return value. - void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr, - ExplodedNode *Pred, ProgramStateRef State); + void conservativeEvalCall( + const CallEvent &Call, NodeBuilder &Bldr, ExplodedNode *Pred, + ProgramStateRef State, InvalidatedSymbols *IS, + RegionAndSymbolInvalidationTraits *ETraits, + StoreManager::InvalidatedRegions *TopLevelInvalidated); /// Either inline or process the call conservatively (or both), based /// on DynamicDispatchBifurcation data. - void BifurcateCall(const MemRegion *BifurReg, - const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, - ExplodedNode *Pred); + void BifurcateCall(const MemRegion *BifurReg, const CallEvent &Call, + const Decl *D, NodeBuilder &Bldr, ExplodedNode *Pred, + InvalidatedSymbols *IS, + RegionAndSymbolInvalidationTraits *ETraits, + StoreManager::InvalidatedRegions *TopLevelInvalidated); bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC); Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -275,23 +275,27 @@ /// pointer). For example, due to it being passed as an argument in a /// call. /// \param IS the set of invalidated symbols. + /// \param NewIS the set of symbols stored into escaped regions that needs + /// escaping later on. /// \param Call if non-null, the invalidated regions represent parameters to /// the call and should be considered directly invalidated. /// \param ITraits information about special handling for a particular /// region/symbol. - LLVM_NODISCARD ProgramStateRef - invalidateRegions(ArrayRef Regions, const Expr *E, - unsigned BlockCount, const LocationContext *LCtx, - bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, - const CallEvent *Call = nullptr, - RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; - - LLVM_NODISCARD ProgramStateRef - invalidateRegions(ArrayRef Regions, const Expr *E, - unsigned BlockCount, const LocationContext *LCtx, - bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, - const CallEvent *Call = nullptr, - RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; + LLVM_NODISCARD ProgramStateRef invalidateRegions( + ArrayRef Regions, const Expr *E, unsigned BlockCount, + const LocationContext *LCtx, bool CausesPointerEscape, + InvalidatedSymbols *IS = nullptr, InvalidatedSymbols *NewIS = nullptr, + StoreManager::InvalidatedRegions *TopLevelInvalidated = nullptr, + const CallEvent *Call = nullptr, + RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; + + LLVM_NODISCARD ProgramStateRef invalidateRegions( + ArrayRef Regions, const Expr *E, unsigned BlockCount, + const LocationContext *LCtx, bool CausesPointerEscape, + InvalidatedSymbols *IS = nullptr, InvalidatedSymbols *NewIS = nullptr, + StoreManager::InvalidatedRegions *TopLevelInvalidated = nullptr, + const CallEvent *Call = nullptr, + RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; /// enterStackFrame - Returns the state for entry to the given stack frame, /// preserving the current state. @@ -445,6 +449,8 @@ const LocationContext *LCtx, bool ResultsInSymbolEscape, InvalidatedSymbols *IS, + InvalidatedSymbols *NewIS, + StoreManager::InvalidatedRegions *TopLevelInvalidated, RegionAndSymbolInvalidationTraits *HTraits, const CallEvent *Call) const; }; Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -222,6 +222,8 @@ /// globals should get invalidated. /// \param[in,out] IS A set to fill with any symbols that are no longer /// accessible. Pass \c NULL if this information will not be used. + /// \param[in,out] NewIS A set to fill with any symbols that are conjured + /// into a region that we cannot reason about, thus is escaped. /// \param[in] ITraits Information about invalidation for a particular /// region/symbol. /// \param[in,out] InvalidatedTopLevel A vector to fill with regions @@ -237,6 +239,7 @@ const LocationContext *LCtx, const CallEvent *Call, InvalidatedSymbols &IS, + InvalidatedSymbols &NewIS, RegionAndSymbolInvalidationTraits &ITraits, InvalidatedRegions *InvalidatedTopLevel, InvalidatedRegions *Invalidated) = 0; Index: clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -995,7 +995,7 @@ return state->invalidateRegions(R, E, C.blockCount(), LCtx, CausesPointerEscape, nullptr, nullptr, - &ITraits); + nullptr, nullptr, &ITraits); } // If we have a non-region value by chance, just remove the binding. Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -283,8 +283,11 @@ } } -ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount, - ProgramStateRef Orig) const { +ProgramStateRef +CallEvent::invalidateRegions(unsigned BlockCount, ProgramStateRef Orig, + InvalidatedSymbols *NewIS, + RegionAndSymbolInvalidationTraits *ETraits, + StoreManager::InvalidatedRegions *TopLevelInvalidated) const { ProgramStateRef Result = (Orig ? Orig : getState()); // Don't invalidate anything if the callee is marked pure/const. @@ -293,9 +296,11 @@ return Result; SmallVector ValuesToInvalidate; - RegionAndSymbolInvalidationTraits ETraits; + RegionAndSymbolInvalidationTraits ETraitsStore; + if (ETraits == nullptr) + ETraits = &ETraitsStore; - getExtraInvalidatedValues(ValuesToInvalidate, &ETraits); + getExtraInvalidatedValues(ValuesToInvalidate, ETraits); // Indexes of arguments whose values will be preserved by the call. llvm::SmallSet PreserveArgs; @@ -307,9 +312,10 @@ // below for efficiency. if (PreserveArgs.count(Idx)) if (const MemRegion *MR = getArgSVal(Idx).getAsRegion()) - ETraits.setTrait(MR->getBaseRegion(), - RegionAndSymbolInvalidationTraits::TK_PreserveContents); - // TODO: Factor this out + handle the lower level const pointers. + ETraits->setTrait( + MR->getBaseRegion(), + RegionAndSymbolInvalidationTraits::TK_PreserveContents); + // TODO: Factor this out + handle the lower level const pointers. ValuesToInvalidate.push_back(getArgSVal(Idx)); @@ -328,13 +334,16 @@ ValuesToInvalidate.push_back(loc::MemRegionVal(VR)); } + InvalidatedSymbols Syms; + if (!NewIS) + NewIS = &Syms; // Invalidate designated regions using the batch invalidation API. // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate // global variables. - return Result->invalidateRegions(ValuesToInvalidate, getOriginExpr(), - BlockCount, getLocationContext(), - /*CausedByPointerEscape*/ true, - /*Symbols=*/nullptr, this, &ETraits); + return Result->invalidateRegions( + ValuesToInvalidate, getOriginExpr(), BlockCount, getLocationContext(), + /*CausedByPointerEscape*/ true, + /*Symbols=*/nullptr, NewIS, TopLevelInvalidated, this, ETraits); } ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit, Index: clang/lib/StaticAnalyzer/Core/CheckerManager.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ clang/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -23,6 +23,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -647,10 +648,11 @@ /// Run checkers for evaluating a call. /// Only one checker will evaluate the call. -void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, - const ExplodedNodeSet &Src, - const CallEvent &Call, - ExprEngine &Eng) { +void CheckerManager::runCheckersForEvalCall( + ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, + ExprEngine &Eng, InvalidatedSymbols *IS, + RegionAndSymbolInvalidationTraits *ETraits, + StoreManager::InvalidatedRegions *TopLevelInvalidated) { for (const auto Pred : Src) { bool anyEvaluated = false; @@ -687,7 +689,7 @@ // If none of the checkers evaluated the call, ask ExprEngine to handle it. if (!anyEvaluated) { NodeBuilder B(Pred, Dst, Eng.getBuilderContext()); - Eng.defaultEvalCall(B, Pred, Call); + Eng.defaultEvalCall(B, Pred, Call, {}, IS, ETraits, TopLevelInvalidated); } } } Index: clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -18,6 +18,7 @@ #include "clang/Analysis/ConstructionContext.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/SaveAndRestore.h" @@ -579,12 +580,17 @@ getCheckerManager().runCheckersForPreCall(dstPreVisit, Pred, Call, *this); + InvalidatedSymbols IS; + RegionAndSymbolInvalidationTraits ETraits; + StoreManager::InvalidatedRegions TopLevelInvalidated; + // Actually evaluate the function call. We try each of the checkers // to see if the can evaluate the function call, and get a callback at // defaultEvalCall if all of them fail. ExplodedNodeSet dstCallEvaluated; getCheckerManager().runCheckersForEvalCall(dstCallEvaluated, dstPreVisit, - Call, *this); + Call, *this, &IS, &ETraits, + &TopLevelInvalidated); // If there were other constructors called for object-type arguments // of this call, clean them up. @@ -593,8 +599,18 @@ finishArgumentConstruction(dstArgumentCleanup, I, Call); // Finally, run any post-call checks. - getCheckerManager().runCheckersForPostCall(Dst, dstArgumentCleanup, + ExplodedNodeSet dstPostCall; + getCheckerManager().runCheckersForPostCall(dstPostCall, dstArgumentCleanup, Call, *this); + + // Run pointerEscape callback with the newly conjured symbols. + for (auto I : dstPostCall) { + NodeBuilder B(I, Dst, *currBldrCtx); + // TODO: the kind is a lie. + ProgramStateRef newState = getCheckerManager().runCheckersForPointerEscape( + I->getState(), IS, &Call, PSK_DirectEscapeOnCall, &ETraits); + B.generateNode(I->getLocation(), newState, I); + } } ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call, @@ -645,7 +661,7 @@ RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion); State = State->invalidateRegions(TargetR, E, Count, LCtx, /* CausesPointerEscape=*/false, nullptr, - &Call, &ITraits); + nullptr, nullptr, &Call, &ITraits); R = State->getSVal(Target.castAs(), E->getType()); } else { @@ -670,9 +686,10 @@ // Conservatively evaluate call by invalidating regions and binding // a conjured return value. void ExprEngine::conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr, - ExplodedNode *Pred, - ProgramStateRef State) { - State = Call.invalidateRegions(currBldrCtx->blockCount(), State); + ExplodedNode *Pred, ProgramStateRef State, + InvalidatedSymbols *IS,RegionAndSymbolInvalidationTraits *ETraits, + StoreManager::InvalidatedRegions *TopLevelInvalidated) { + State = Call.invalidateRegions(currBldrCtx->blockCount(), State, IS, ETraits, TopLevelInvalidated); State = bindReturnValue(Call, Pred->getLocationContext(), State); // And make the result node. @@ -999,9 +1016,11 @@ return MD->isTrivial(); } -void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred, - const CallEvent &CallTemplate, - const EvalCallOptions &CallOpts) { +void ExprEngine::defaultEvalCall( + NodeBuilder &Bldr, ExplodedNode *Pred, const CallEvent &CallTemplate, + const EvalCallOptions &CallOpts, InvalidatedSymbols *IS, + RegionAndSymbolInvalidationTraits *ETraits, + StoreManager::InvalidatedRegions *TopLevelInvalidated) { // Make sure we have the most recent state attached to the call. ProgramStateRef State = Pred->getState(); CallEventRef<> Call = CallTemplate.cloneWithState(State); @@ -1030,13 +1049,15 @@ // Explore with and without inlining the call. if (Options.getIPAMode() == IPAK_DynamicDispatchBifurcate) { - BifurcateCall(RD.getDispatchRegion(), *Call, D, Bldr, Pred); + BifurcateCall(RD.getDispatchRegion(), *Call, D, Bldr, Pred, IS, + ETraits, TopLevelInvalidated); return; } // Don't inline if we're not in any dynamic dispatch mode. if (Options.getIPAMode() != IPAK_DynamicDispatch) { - conservativeEvalCall(*Call, Bldr, Pred, State); + conservativeEvalCall(*Call, Bldr, Pred, State, IS, ETraits, + TopLevelInvalidated); return; } } @@ -1048,20 +1069,22 @@ } // If we can't inline it, handle the return value and invalidate the regions. - conservativeEvalCall(*Call, Bldr, Pred, State); + conservativeEvalCall(*Call, Bldr, Pred, State, IS, ETraits, + TopLevelInvalidated); } -void ExprEngine::BifurcateCall(const MemRegion *BifurReg, - const CallEvent &Call, const Decl *D, - NodeBuilder &Bldr, ExplodedNode *Pred) { +void ExprEngine::BifurcateCall( + const MemRegion *BifurReg, const CallEvent &Call, const Decl *D, + NodeBuilder &Bldr, ExplodedNode *Pred, InvalidatedSymbols *IS, + RegionAndSymbolInvalidationTraits *ETraits, + StoreManager::InvalidatedRegions *TopLevelInvalidated) { assert(BifurReg); BifurReg = BifurReg->StripCasts(); // Check if we've performed the split already - note, we only want // to split the path once per memory region. ProgramStateRef State = Pred->getState(); - const unsigned *BState = - State->get(BifurReg); + const unsigned *BState = State->get(BifurReg); if (BState) { // If we are on "inline path", keep inlining if possible. if (*BState == DynamicDispatchModeInlined) @@ -1070,21 +1093,21 @@ // If inline failed, or we are on the path where we assume we // don't have enough info about the receiver to inline, conjure the // return value and invalidate the regions. - conservativeEvalCall(Call, Bldr, Pred, State); + conservativeEvalCall(Call, Bldr, Pred, State, IS, ETraits, + TopLevelInvalidated); return; } // If we got here, this is the first time we process a message to this // region, so split the path. - ProgramStateRef IState = - State->set(BifurReg, - DynamicDispatchModeInlined); + ProgramStateRef IState = State->set( + BifurReg, DynamicDispatchModeInlined); inlineCall(Call, D, Bldr, Pred, IState); - ProgramStateRef NoIState = - State->set(BifurReg, - DynamicDispatchModeConservative); - conservativeEvalCall(Call, Bldr, Pred, NoIState); + ProgramStateRef NoIState = State->set( + BifurReg, DynamicDispatchModeConservative); + conservativeEvalCall(Call, Bldr, Pred, NoIState, IS, ETraits, + TopLevelInvalidated); NumOfDynamicDispatchPathSplits++; } Index: clang/lib/StaticAnalyzer/Core/LoopWidening.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/LoopWidening.cpp +++ clang/lib/StaticAnalyzer/Core/LoopWidening.cpp @@ -92,7 +92,7 @@ return PrevState->invalidateRegions(Regions, getLoopCondition(LoopStmt), BlockCount, LCtx, true, nullptr, nullptr, - &ITraits); + nullptr, nullptr, &ITraits); } } // end namespace ento Index: clang/lib/StaticAnalyzer/Core/ProgramState.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -150,72 +150,68 @@ typedef ArrayRef RegionList; typedef ArrayRef ValueList; -ProgramStateRef -ProgramState::invalidateRegions(RegionList Regions, - const Expr *E, unsigned Count, - const LocationContext *LCtx, - bool CausedByPointerEscape, - InvalidatedSymbols *IS, - const CallEvent *Call, - RegionAndSymbolInvalidationTraits *ITraits) const { +ProgramStateRef ProgramState::invalidateRegions( + RegionList Regions, const Expr *E, unsigned Count, + const LocationContext *LCtx, bool CausedByPointerEscape, + InvalidatedSymbols *IS, InvalidatedSymbols *NewIS, + StoreManager::InvalidatedRegions *TopLevelInvalidated, + const CallEvent *Call, RegionAndSymbolInvalidationTraits *ITraits) const { SmallVector Values; - for (RegionList::const_iterator I = Regions.begin(), - End = Regions.end(); I != End; ++I) + for (RegionList::const_iterator I = Regions.begin(), End = Regions.end(); + I != End; ++I) Values.push_back(loc::MemRegionVal(*I)); return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape, - IS, ITraits, Call); + IS, NewIS, TopLevelInvalidated, ITraits, Call); } -ProgramStateRef -ProgramState::invalidateRegions(ValueList Values, - const Expr *E, unsigned Count, - const LocationContext *LCtx, - bool CausedByPointerEscape, - InvalidatedSymbols *IS, - const CallEvent *Call, - RegionAndSymbolInvalidationTraits *ITraits) const { +ProgramStateRef ProgramState::invalidateRegions( + ValueList Values, const Expr *E, unsigned Count, + const LocationContext *LCtx, bool CausedByPointerEscape, + InvalidatedSymbols *IS, InvalidatedSymbols *NewIS, + StoreManager::InvalidatedRegions *TopLevelInvalidated, + const CallEvent *Call, RegionAndSymbolInvalidationTraits *ITraits) const { return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape, - IS, ITraits, Call); + IS, NewIS, TopLevelInvalidated, ITraits, Call); } -ProgramStateRef -ProgramState::invalidateRegionsImpl(ValueList Values, - const Expr *E, unsigned Count, - const LocationContext *LCtx, - bool CausedByPointerEscape, - InvalidatedSymbols *IS, - RegionAndSymbolInvalidationTraits *ITraits, - const CallEvent *Call) const { +ProgramStateRef ProgramState::invalidateRegionsImpl( + ValueList Values, const Expr *E, unsigned Count, + const LocationContext *LCtx, bool CausedByPointerEscape, + InvalidatedSymbols *IS, InvalidatedSymbols *NewIS, + StoreManager::InvalidatedRegions *TopLevelInvalidated, + RegionAndSymbolInvalidationTraits *ITraits, const CallEvent *Call) const { ProgramStateManager &Mgr = getStateManager(); SubEngine &Eng = Mgr.getOwningEngine(); InvalidatedSymbols InvalidatedSyms; + InvalidatedSymbols NewSyms; if (!IS) IS = &InvalidatedSyms; + if (!NewIS) + NewIS = &NewSyms; RegionAndSymbolInvalidationTraits ITraitsLocal; if (!ITraits) ITraits = &ITraitsLocal; - StoreManager::InvalidatedRegions TopLevelInvalidated; + StoreManager::InvalidatedRegions TopLevelInvalidatedStore; + if (TopLevelInvalidated == nullptr) + TopLevelInvalidated = &TopLevelInvalidatedStore; StoreManager::InvalidatedRegions Invalidated; - const StoreRef &newStore - = Mgr.StoreMgr->invalidateRegions(getStore(), Values, E, Count, LCtx, Call, - *IS, *ITraits, &TopLevelInvalidated, - &Invalidated); + const StoreRef &newStore = Mgr.StoreMgr->invalidateRegions( + getStore(), Values, E, Count, LCtx, Call, *IS, *NewIS, *ITraits, + TopLevelInvalidated, &Invalidated); ProgramStateRef newState = makeWithStore(newStore); if (CausedByPointerEscape) { - newState = Eng.notifyCheckersOfPointerEscape(newState, IS, - TopLevelInvalidated, - Call, - *ITraits); + newState = Eng.notifyCheckersOfPointerEscape( + newState, IS, *TopLevelInvalidated, Call, *ITraits); } - return Eng.processRegionChanges(newState, IS, TopLevelInvalidated, + return Eng.processRegionChanges(newState, IS, *TopLevelInvalidated, Invalidated, LCtx, Call); } Index: clang/lib/StaticAnalyzer/Core/RegionStore.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -428,6 +428,7 @@ const LocationContext *LCtx, const CallEvent *Call, InvalidatedSymbols &IS, + InvalidatedSymbols &NewIS, RegionAndSymbolInvalidationTraits &ITraits, InvalidatedRegions *Invalidated, InvalidatedRegions *InvalidatedTopLevel) override; @@ -997,22 +998,22 @@ unsigned Count; const LocationContext *LCtx; InvalidatedSymbols &IS; + // Newly conjured symbols that should be invalidated later. + InvalidatedSymbols &NewIS; RegionAndSymbolInvalidationTraits &ITraits; StoreManager::InvalidatedRegions *Regions; GlobalsFilterKind GlobalsFilter; public: - InvalidateRegionsWorker(RegionStoreManager &rm, - ProgramStateManager &stateMgr, - RegionBindingsRef b, - const Expr *ex, unsigned count, - const LocationContext *lctx, - InvalidatedSymbols &is, + InvalidateRegionsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr, + RegionBindingsRef b, const Expr *ex, unsigned count, + const LocationContext *lctx, InvalidatedSymbols &is, + InvalidatedSymbols &newIs, RegionAndSymbolInvalidationTraits &ITraitsIn, StoreManager::InvalidatedRegions *r, GlobalsFilterKind GFK) - : ClusterAnalysis(rm, stateMgr, b), - Ex(ex), Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r), - GlobalsFilter(GFK) {} + : ClusterAnalysis(rm, stateMgr, b), Ex(ex), + Count(count), LCtx(lctx), IS(is), NewIS(newIs), ITraits(ITraitsIn), + Regions(r), GlobalsFilter(GFK) {} void VisitCluster(const MemRegion *baseR, const ClusterBindings *C); void VisitBinding(SVal V); @@ -1150,6 +1151,8 @@ DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(baseR, Ex, LCtx, Ctx.IntTy, Count); B = B.addBinding(baseR, BindingKey::Default, V); + if (isa(baseR)) + NewIS.insert(V.getAsSymbol()); return; } @@ -1338,6 +1341,7 @@ const LocationContext *LCtx, const CallEvent *Call, InvalidatedSymbols &IS, + InvalidatedSymbols &NewIS, RegionAndSymbolInvalidationTraits &ITraits, InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) { @@ -1352,8 +1356,8 @@ } RegionBindingsRef B = getRegionBindings(store); - InvalidateRegionsWorker W(*this, StateMgr, B, Ex, Count, LCtx, IS, ITraits, - Invalidated, GlobalsFilter); + InvalidateRegionsWorker W(*this, StateMgr, B, Ex, Count, LCtx, IS, NewIS, + ITraits, Invalidated, GlobalsFilter); // Scan the bindings and generate the clusters. W.GenerateClusters();