Author: charusso
Date: Wed May 29 08:25:19 2019
New Revision: 361972

URL: http://llvm.org/viewvc/llvm-project?rev=361972&view=rev
Log:
[analyzer] print() JSONify: Store implementation

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/D61912

Added:
    cfe/trunk/include/clang/Basic/JsonSupport.h
Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
    cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
    cfe/trunk/test/Analysis/expr-inspection.c

Added: cfe/trunk/include/clang/Basic/JsonSupport.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/JsonSupport.h?rev=361972&view=auto
==============================================================================
--- cfe/trunk/include/clang/Basic/JsonSupport.h (added)
+++ cfe/trunk/include/clang/Basic/JsonSupport.h Wed May 29 08:25:19 2019
@@ -0,0 +1,27 @@
+//===- JsonSupport.h - JSON Output Utilities --------------------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_JSONSUPPORT_H
+#define LLVM_CLANG_BASIC_JSONSUPPORT_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/Support/raw_ostream.h"
+
+
+namespace clang {
+
+inline raw_ostream &Indent(raw_ostream &Out, const unsigned int Space,
+                           bool IsDot) {
+  for (unsigned int I = 0; I < Space * 2; ++I)
+    Out << (IsDot ? "&nbsp;" : " ");
+  return Out;
+}
+
+} // namespace clang
+
+#endif // LLVM_CLANG_BASIC_JSONSUPPORT_H

Modified: 
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h?rev=361972&r1=361971&r2=361972&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h 
(original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h 
Wed May 29 08:25:19 2019
@@ -424,10 +424,12 @@ public:
   }
 
   // Pretty-printing.
-  void print(raw_ostream &Out, const char *nl = "\n", const char *sep = "",
-             const LocationContext *CurrentLC = nullptr) const;
-  void printDOT(raw_ostream &Out,
-                const LocationContext *CurrentLC = nullptr) const;
+  void printJson(raw_ostream &Out, const LocationContext *LCtx = nullptr,
+                 const char *NL = "\n", const char *Sep = "",
+                 unsigned int Space = 0, bool IsDot = false) const;
+
+  void printDOT(raw_ostream &Out, const LocationContext *LCtx = nullptr,
+                unsigned int Space = 0) const;
 
   void dump() const;
 

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h?rev=361972&r1=361971&r2=361972&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h Wed May 
29 08:25:19 2019
@@ -253,7 +253,8 @@ public:
   virtual bool scanReachableSymbols(Store S, const MemRegion *R,
                                     ScanReachableSymbols &Visitor) = 0;
 
-  virtual void print(Store store, raw_ostream &Out, const char* nl) = 0;
+  virtual void printJson(raw_ostream &Out, Store S, const char *NL,
+                         unsigned int Space, bool IsDot) const = 0;
 
   class BindingsHandler {
   public:

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=361972&r1=361971&r2=361972&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Wed May 29 08:25:19 2019
@@ -440,16 +440,16 @@ void ProgramState::setStore(const StoreR
 //  State pretty-printing.
 
//===----------------------------------------------------------------------===//
 
-void ProgramState::print(raw_ostream &Out,
-                         const char *NL, const char *Sep,
-                         const LocationContext *LC) const {
+void ProgramState::printJson(raw_ostream &Out, const LocationContext *LCtx,
+                             const char *NL, const char *Sep,
+                             unsigned int Space, bool IsDot) const {
   // Print the store.
   ProgramStateManager &Mgr = getStateManager();
   const ASTContext &Context = getStateManager().getContext();
-  Mgr.getStoreManager().print(getStore(), Out, NL);
+  Mgr.getStoreManager().printJson(Out, getStore(), NL, Space, IsDot);
 
   // Print out the environment.
-  Env.print(Out, NL, Sep, Context, LC);
+  Env.print(Out, NL, Sep, Context, LCtx);
 
   // Print out the constraints.
   Mgr.getConstraintManager().print(this, Out, NL, Sep);
@@ -458,16 +458,16 @@ void ProgramState::print(raw_ostream &Ou
   printDynamicTypeInfo(this, Out, NL, Sep);
 
   // Print checker-specific data.
-  Mgr.getOwningEngine().printState(Out, this, NL, Sep, LC);
+  Mgr.getOwningEngine().printState(Out, this, NL, Sep, LCtx);
 }
 
-void ProgramState::printDOT(raw_ostream &Out,
-                            const LocationContext *LC) const {
-  print(Out, "\\l", "\\|", LC);
+void ProgramState::printDOT(raw_ostream &Out, const LocationContext *LCtx,
+                            unsigned int Space) const {
+  printJson(Out, LCtx, "\\l", "\\|", Space, /*IsDot=*/true);
 }
 
 LLVM_DUMP_METHOD void ProgramState::dump() const {
-  print(llvm::errs());
+  printJson(llvm::errs());
 }
 
 AnalysisManager& ProgramState::getAnalysisManager() const {

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=361972&r1=361971&r2=361972&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Wed May 29 08:25:19 2019
@@ -19,6 +19,7 @@
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Basic/JsonSupport.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
@@ -120,21 +121,21 @@ BindingKey BindingKey::Make(const MemReg
 }
 
 namespace llvm {
-  static inline
-  raw_ostream &operator<<(raw_ostream &os, BindingKey K) {
-    os << '(' << K.getRegion();
-    if (!K.hasSymbolicOffset())
-      os << ',' << K.getOffset();
-    os << ',' << (K.isDirect() ? "direct" : "default")
-       << ')';
-    return os;
-  }
+static inline raw_ostream &operator<<(raw_ostream &Out, BindingKey K) {
+  Out << "\"kind\": \"" << (K.isDirect() ? "Direct" : "Default")
+      << "\", \"offset\": ";
+
+  if (!K.hasSymbolicOffset())
+    Out << K.getOffset();
+  else
+    Out << "null";
 
-} // end llvm namespace
+  return Out;
+}
+
+} // namespace llvm
 
-#ifndef NDEBUG
 LLVM_DUMP_METHOD void BindingKey::dump() const { llvm::errs() << *this; }
-#endif
 
 
//===----------------------------------------------------------------------===//
 // Actual Store type.
@@ -206,18 +207,31 @@ public:
     return asImmutableMap().getRootWithoutRetain();
   }
 
-  void dump(raw_ostream &OS, const char *nl) const {
-   for (iterator I = begin(), E = end(); I != E; ++I) {
-     const ClusterBindings &Cluster = I.getData();
-     for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
-          CI != CE; ++CI) {
-       OS << ' ' << CI.getKey() << " : " << CI.getData() << nl;
-     }
-     OS << nl;
-   }
+  void printJson(raw_ostream &Out, const char *NL = "\n",
+                 unsigned int Space = 0, bool IsDot = false) const {
+    for (iterator I = begin(); I != end(); ++I) {
+      Indent(Out, Space, IsDot)
+          << "{ \"cluster\": \"" << I.getKey() << "\", \"items\": [" << NL;
+
+      ++Space;
+      const ClusterBindings &CB = I.getData();
+      for (ClusterBindings::iterator CI = CB.begin(); CI != CB.end(); ++CI) {
+        Indent(Out, Space, IsDot) << "{ " << CI.getKey() << ", \"value\": \""
+                                  << CI.getData() << "\" }";
+        if (std::next(CI) != CB.end())
+          Out << ',';
+        Out << NL;
+      }
+
+      --Space;
+      Indent(Out, Space, IsDot) << "]}";
+      if (std::next(I) != end())
+        Out << ',';
+      Out << NL;
+    }
   }
 
-  LLVM_DUMP_METHOD void dump() const { dump(llvm::errs(), "\n"); }
+  LLVM_DUMP_METHOD void dump() const { printJson(llvm::errs()); }
 };
 } // end anonymous namespace
 
@@ -594,7 +608,8 @@ public: // Part of public interface to c
                              RBFactory.getTreeFactory());
   }
 
-  void print(Store store, raw_ostream &Out, const char* nl) override;
+  void printJson(raw_ostream &Out, Store S, const char *NL = "\n",
+                 unsigned int Space = 0, bool IsDot = false) const override;
 
   void iterBindings(Store store, BindingsHandler& f) override {
     RegionBindingsRef B = getRegionBindings(store);
@@ -2611,11 +2626,18 @@ StoreRef RegionStoreManager::removeDeadB
 // Utility methods.
 
//===----------------------------------------------------------------------===//
 
-void RegionStoreManager::print(Store store, raw_ostream &OS,
-                               const char* nl) {
-  RegionBindingsRef B = getRegionBindings(store);
-  OS << "Store (direct and default bindings), "
-     << B.asStore()
-     << " :" << nl;
-  B.dump(OS, nl);
+void RegionStoreManager::printJson(raw_ostream &Out, Store S, const char *NL,
+                                   unsigned int Space, bool IsDot) const {
+  RegionBindingsRef Bindings = getRegionBindings(S);
+
+  Indent(Out, Space, IsDot) << "\"store\": ";
+
+  if (Bindings.isEmpty()) {
+    Out << "null," << NL;
+    return;
+  }
+
+  Out << '[' << NL;
+  Bindings.printJson(Out, NL, ++Space, IsDot);
+  Indent(Out, --Space, IsDot) << "]," << NL;
 }

Modified: cfe/trunk/test/Analysis/expr-inspection.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/expr-inspection.c?rev=361972&r1=361971&r2=361972&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/expr-inspection.c (original)
+++ cfe/trunk/test/Analysis/expr-inspection.c Wed May 29 08:25:19 2019
@@ -1,4 +1,6 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection -verify %s 
2>&1 | FileCheck %s
+// RUN: %clang_analyze_cc1 \
+// RUN:  -analyzer-checker=debug.ExprInspection \
+// RUN:  -verify %s 2>&1 | FileCheck %s
 
 // Self-tests for the debug.ExprInspection checker.
 
@@ -10,16 +12,26 @@ void foo(int x) {
   clang_analyzer_dump(x); // expected-warning{{reg_$0<int x>}}
   clang_analyzer_dump(x + (-1)); // expected-warning{{(reg_$0<int x>) + -1}}
   int y = 1;
-  clang_analyzer_printState();
-  for (; y < 3; ++y)
+  for (; y < 3; ++y) {
     clang_analyzer_numTimesReached(); // expected-warning{{2}}
+
+    if (y == 2) {
+      int z = x > 13;
+      if (!z)
+        clang_analyzer_printState();
+    }
+  }
 }
 
-// CHECK: Store (direct and default bindings)
-// CHECK-NEXT: (y,0,direct) : 1 S32b
+// CHECK:      "store": [
+// CHECK-NEXT:   { "cluster": "y", "items": [
+// CHECK-NEXT:     { "kind": "Direct", "offset": 0, "value": "2 S32b" }
+// CHECK-NEXT:   ]}
+// CHECK-NEXT: ]
 
-// CHECK: Expressions by stack frame:
+// CHECK:      Expressions by stack frame:
 // CHECK-NEXT: #0 Calling foo
-// CHECK-NEXT: clang_analyzer_printState : &code{clang_analyzer_printState}
+// CHECK-NEXT: (LC1, S847) clang_analyzer_printState : 
&code{clang_analyzer_printState}
 
-// CHECK: {{(Ranges are empty.)|(Constraints:[[:space:]]*$)}}
+// CHECK:      Ranges of symbol values:
+// CHECK-NEXT:  reg_$0<int x> : { [-2147483648, 13] }


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to