]> granicus.if.org Git - clang/commitdiff
[analyzer] Self-debug: Dump the core's internal state traits to the egraph.
authorArtem Dergachev <artem.dergachev@gmail.com>
Thu, 8 Feb 2018 22:32:38 +0000 (22:32 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Thu, 8 Feb 2018 22:32:38 +0000 (22:32 +0000)
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

include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
lib/StaticAnalyzer/Core/ExprEngine.cpp
lib/StaticAnalyzer/Core/ProgramState.cpp

index 1030a1f51ba46aa4aabf38b1ab6fbee4fc9167e9..ef06d12795ff288d1a832a195edec2439a227384 100644 (file)
@@ -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; }
 
index 8ccd34751bbe140261055d11e25cd337939de8e9..8341fd0f4fab32b364ce7cc046a214e772f6065f 100644 (file)
@@ -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.
index 39f36477bdee1db2c1a3b268314aeba750282e47..3df69e891b7d3fc229dde983484dd7261cad7c17 100644 (file)
@@ -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<InitializedTemporariesSet>()) {
+    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<CXXNewAllocatorValues>()) {
+    std::pair<const CXXNewExpr *, const LocationContext *> 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<InitializedTemporariesSet>().isEmpty()) {
+      Out << Sep << "Initialized temporaries:" << NL;
+
+      LCtx->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
+        printInitializedTemporariesForContext(Out, State, NL, Sep, LC);
+      });
+    }
+
+    if (!State->get<CXXNewAllocatorValues>().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);
 }
 
index 53646e295efc4c6e7069bf0d1188146117fd4566..eccbc30bbe538a1e08448333764ca8f45c0613c6 100644 (file)
@@ -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 {