From 0b84c86812b3589a77e46d9a019885d4589b5f40 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Thu, 8 Feb 2018 22:32:38 +0000 Subject: [PATCH] [analyzer] Self-debug: Dump the core's internal state traits to the egraph. It is useful for debugging problems with C++ operator new() or temporaries. Differential Revision: https://reviews.llvm.org/D42560 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@324663 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/PathSensitive/ExprEngine.h | 5 +- .../Core/PathSensitive/SubEngine.h | 3 +- lib/StaticAnalyzer/Core/ExprEngine.cpp | 56 ++++++++++++++++++- lib/StaticAnalyzer/Core/ProgramState.cpp | 2 +- 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 1030a1f51b..ef06d12795 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -299,8 +299,9 @@ public: 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; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index 8ccd34751b..8341fd0f4f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -155,7 +155,8 @@ public: /// 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. diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 39f36477bd..3df69e891b 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -383,8 +383,62 @@ ExprEngine::processRegionChanges(ProgramStateRef state, LCtx, Call); } +static void printInitializedTemporariesForContext(raw_ostream &Out, + ProgramStateRef State, + const char *NL, + const char *Sep, + const LocationContext *LC) { + PrintingPolicy PP = + LC->getAnalysisDeclContext()->getASTContext().getPrintingPolicy(); + for (auto I : State->get()) { + if (I.second != LC) + continue; + Out << '(' << I.second << ',' << I.first << ") "; + I.first->printPretty(Out, nullptr, PP); + Out << NL; + } +} + +static void printCXXNewAllocatorValuesForContext(raw_ostream &Out, + ProgramStateRef State, + const char *NL, + const char *Sep, + const LocationContext *LC) { + PrintingPolicy PP = + LC->getAnalysisDeclContext()->getASTContext().getPrintingPolicy(); + + for (auto I : State->get()) { + std::pair Key = I.first; + SVal Value = I.second; + if (Key.second != LC) + continue; + Out << '(' << Key.second << ',' << Key.first << ") "; + Key.first->printPretty(Out, nullptr, PP); + Out << " : " << Value << NL; + } +} + 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) { + if (!State->get().isEmpty()) { + Out << Sep << "Initialized temporaries:" << NL; + + LCtx->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) { + printInitializedTemporariesForContext(Out, State, NL, Sep, LC); + }); + } + + if (!State->get().isEmpty()) { + Out << Sep << "operator new() allocator return values:" << NL; + + LCtx->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) { + printCXXNewAllocatorValuesForContext(Out, State, NL, Sep, LC); + }); + } + } + getCheckerManager().runCheckersForPrintState(Out, State, NL, Sep); } diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp index 53646e295e..eccbc30bbe 100644 --- a/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -450,7 +450,7 @@ void ProgramState::print(raw_ostream &Out, const char *NL, const char *Sep, 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 { -- 2.40.0