Index: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -299,8 +299,9 @@ const CallEvent *Call) override; /// printState - Called by ProgramStateManager to print checker-specific data. - void printState(raw_ostream &Out, ProgramStateRef State, - const char *NL, const char *Sep) override; + void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, + const char *Sep, + const LocationContext *LCtx = nullptr) override; ProgramStateManager& getStateManager() override { return StateMgr; } Index: include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h =================================================================== --- include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -155,7 +155,8 @@ /// printState - Called by ProgramStateManager to print checker-specific data. virtual void printState(raw_ostream &Out, ProgramStateRef State, - const char *NL, const char *Sep) = 0; + const char *NL, const char *Sep, + const LocationContext *LCtx = nullptr) = 0; /// Called by CoreEngine when the analysis worklist is either empty or the // maximum number of analysis steps have been reached. Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -384,7 +384,44 @@ } void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State, - const char *NL, const char *Sep) { + const char *NL, const char *Sep, + const LocationContext *LCtx) { + if (LCtx) { + LangOptions LO; // FIXME. + + auto InitTempSet = State->get(); + if (!InitTempSet.isEmpty()) { + Out << Sep << "Initialized temporaries:" << NL; + + LCtx->dumpStack(Out, "", NL, Sep, + [&Out, &LO, InitTempSet, NL](const LocationContext *LC) { + for (auto I : InitTempSet) { + if (I.second != LC) + continue; + Out << '(' << I.second << ',' << I.first << ") "; + I.first->printPretty(Out, nullptr, PrintingPolicy(LO)); + Out << NL; + } + }); + } + + auto NewAllocValsMap = State->get(); + if (!NewAllocValsMap.isEmpty()) { + Out << Sep << "operator new() allocator return values:" << NL; + + LCtx->dumpStack(Out, "", NL, Sep, + [&Out, &LO, NewAllocValsMap, NL](const LocationContext *LC) { + for (auto I : NewAllocValsMap) { + if (I.first.second != LC) + continue; + Out << '(' << I.first.second << ',' << I.first.first << ") "; + I.first.first->printPretty(Out, nullptr, PrintingPolicy(LO)); + Out << " : " << I.second << NL; + } + }); + } + } + getCheckerManager().runCheckersForPrintState(Out, State, NL, Sep); } Index: lib/StaticAnalyzer/Core/ProgramState.cpp =================================================================== --- lib/StaticAnalyzer/Core/ProgramState.cpp +++ lib/StaticAnalyzer/Core/ProgramState.cpp @@ -450,7 +450,7 @@ Mgr.getConstraintManager().print(this, Out, NL, Sep); // Print checker-specific data. - Mgr.getOwningEngine()->printState(Out, this, NL, Sep); + Mgr.getOwningEngine()->printState(Out, this, NL, Sep, LC); } void ProgramState::printDOT(raw_ostream &Out, const LocationContext *LC) const {