[analyzer] print() JSONify: Constraints implementation
authorCsaba Dabis <dabis.csaba98@gmail.com>
Wed, 29 May 2019 15:43:26 +0000 (15:43 +0000)
committerCsaba Dabis <dabis.csaba98@gmail.com>
Wed, 29 May 2019 15:43:26 +0000 (15:43 +0000)
Summary: -

Reviewers: NoQ, xazax.hun, ravikandhadai, baloghadamsoftware, Szelethus

Reviewed By: NoQ

Subscribers: szepet, rnkovacs, a.sidorin, mikhail.ramalho, donat.nagy,
             dkrupp

Tags: #clang

Differential Revision: https://reviews.llvm.org/D62082

llvm-svn: 361978

clang/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h
clang/lib/StaticAnalyzer/Core/ProgramState.cpp
clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
clang/test/Analysis/expr-inspection.c

index 5b69299..1baf8c5 100644 (file)
@@ -162,10 +162,9 @@ public:
   virtual ProgramStateRef removeDeadBindings(ProgramStateRef state,
                                                  SymbolReaper& SymReaper) = 0;
 
-  virtual void print(ProgramStateRef state,
-                     raw_ostream &Out,
-                     const char* nl,
-                     const char *sep) = 0;
+  virtual void printJson(raw_ostream &Out, ProgramStateRef State,
+                         const char *NL, unsigned int Space,
+                         bool IsDot) const = 0;
 
   virtual void EndPath(ProgramStateRef state) {}
 
index fe097b9..1712501 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H
 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H
 
+#include "clang/Basic/JsonSupport.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h"
 
@@ -208,17 +209,32 @@ public:
     return State->set<ConstraintSMT>(CZ);
   }
 
-  void print(ProgramStateRef St, raw_ostream &OS, const char *nl,
-             const char *sep) override {
+  void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL = "\n",
+                 unsigned int Space = 0, bool IsDot = false) const override {
+    ConstraintSMTType Constraints = State->get<ConstraintSMT>();
 
-    auto CZ = St->get<ConstraintSMT>();
+    Indent(Out, Space, IsDot) << "\"constraints\": ";
+    if (Constraints.isEmpty()) {
+      Out << "null," << NL;
+      return;
+    }
 
-    OS << nl << sep << "Constraints:";
-    for (auto I = CZ.begin(), E = CZ.end(); I != E; ++I) {
-      OS << nl << ' ' << I->first << " : ";
-      I->second->print(OS);
+    ++Space;
+    Out << '[' << NL;
+    for (ConstraintSMTType::iterator I = Constraints.begin();
+         I != Constraints.end(); ++I) {
+      Indent(Out, Space, IsDot)
+          << "{ \"symbol\": \"" << I->first << "\", \"range\": \"";
+      I->second->print(Out);
+      Out << "\" }";
+
+      if (std::next(I) != Constraints.end())
+        Out << ',';
+      Out << NL;
     }
-    OS << nl;
+
+    --Space;
+    Indent(Out, Space, IsDot) << "],";
   }
 
   bool haveEqualConstraints(ProgramStateRef S1,
index 911b96d..090801f 100644 (file)
@@ -452,7 +452,7 @@ void ProgramState::printJson(raw_ostream &Out, const LocationContext *LCtx,
   Env.printJson(Out, Context, LCtx, NL, Space, IsDot);
 
   // Print out the constraints.
-  Mgr.getConstraintManager().print(this, Out, NL, Sep);
+  Mgr.getConstraintManager().printJson(Out, this, NL, Space, IsDot);
 
   // Print out the tracked dynamic types.
   printDynamicTypeInfo(this, Out, NL, Sep);
index 5c3eb0d..6472422 100644 (file)
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/Basic/JsonSupport.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
@@ -261,8 +262,8 @@ public:
   ProgramStateRef removeDeadBindings(ProgramStateRef State,
                                      SymbolReaper &SymReaper) override;
 
-  void print(ProgramStateRef State, raw_ostream &Out, const char *nl,
-             const char *sep) override;
+  void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL = "\n",
+                 unsigned int Space = 0, bool IsDot = false) const override;
 
   //===------------------------------------------------------------------===//
   // Implementation for interface from RangedConstraintManager.
@@ -754,25 +755,35 @@ ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange(
   return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New);
 }
 
-//===------------------------------------------------------------------------===
+//===----------------------------------------------------------------------===//
 // Pretty-printing.
-//===------------------------------------------------------------------------===/
-
-void RangeConstraintManager::print(ProgramStateRef St, raw_ostream &Out,
-                                   const char *nl, const char *sep) {
+//===----------------------------------------------------------------------===//
 
-  ConstraintRangeTy Ranges = St->get<ConstraintRange>();
+void RangeConstraintManager::printJson(raw_ostream &Out, ProgramStateRef State,
+                                       const char *NL, unsigned int Space,
+                                       bool IsDot) const {
+  ConstraintRangeTy Constraints = State->get<ConstraintRange>();
 
-  if (Ranges.isEmpty()) {
-    Out << nl << sep << "Ranges are empty." << nl;
+  Indent(Out, Space, IsDot) << "\"constraints\": ";
+  if (Constraints.isEmpty()) {
+    Out << "null," << NL;
     return;
   }
 
-  Out << nl << sep << "Ranges of symbol values:";
-  for (ConstraintRangeTy::iterator I = Ranges.begin(), E = Ranges.end(); I != E;
-       ++I) {
-    Out << nl << ' ' << I.getKey() << " : ";
+  ++Space;
+  Out << '[' << NL;
+  for (ConstraintRangeTy::iterator I = Constraints.begin();
+       I != Constraints.end(); ++I) {
+    Indent(Out, Space, IsDot)
+        << "{ \"symbol\": \"" << I.getKey() << "\", \"range\": \"";
     I.getData().print(Out);
+    Out << "\" }";
+
+    if (std::next(I) != Constraints.end())
+      Out << ',';
+    Out << NL;
   }
-  Out << nl;
+
+  --Space;
+  Indent(Out, Space, IsDot) << "]," << NL;
 }
index fe3191e..461252d 100644 (file)
@@ -33,6 +33,7 @@ void foo(int x) {
 // CHECK-NEXT:     { "lctx_id": 1, "stmt_id": 847, "pretty": "clang_analyzer_printState", "value": "&code{clang_analyzer_printState}" }
 // CHECK-NEXT:   ]}
 // CHECK-NEXT: ],
+// CHECK-NEXT: "constraints": [
+// CHECK-NEXT:   { "symbol": "reg_$0<int x>", "range": "{ [-2147483648, 13] }" }
+// CHECK-NEXT: ],
 
-// CHECK:      Ranges of symbol values:
-// CHECK-NEXT:  reg_$0<int x> : { [-2147483648, 13] }