r361976 - [analyzer] print() JSONify: Environment implementation
Csaba Dabis via cfe-commits
cfe-commits at lists.llvm.org
Wed May 29 08:36:58 PDT 2019
Author: charusso
Date: Wed May 29 08:36:58 2019
New Revision: 361976
URL: http://llvm.org/viewvc/llvm-project?rev=361976&view=rev
Log:
[analyzer] print() JSONify: Environment 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/D62081
Modified:
cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp
cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h
cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
cfe/trunk/test/Analysis/expr-inspection.c
Modified: cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h?rev=361976&r1=361975&r2=361976&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h (original)
+++ cfe/trunk/include/clang/Analysis/AnalysisDeclContext.h Wed May 29 08:36:58 2019
@@ -274,11 +274,17 @@ public:
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
void dumpStack(
- raw_ostream &OS, StringRef Indent = {}, const char *NL = "\n",
- const char *Sep = "",
+ raw_ostream &Out, const char *NL = "\n",
std::function<void(const LocationContext *)> printMoreInfoPerContext =
[](const LocationContext *) {}) const;
- void dumpStack() const;
+
+ void printJson(
+ raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0,
+ bool IsDot = false,
+ std::function<void(const LocationContext *)> printMoreInfoPerContext =
+ [](const LocationContext *) {}) const;
+
+ void dump() const;
public:
static void ProfileCommon(llvm::FoldingSetNodeID &ID,
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h?rev=361976&r1=361975&r2=361976&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h Wed May 29 08:36:58 2019
@@ -91,9 +91,9 @@ public:
return ExprBindings == RHS.ExprBindings;
}
- void print(raw_ostream &Out, const char *NL, const char *Sep,
- const ASTContext &Context,
- const LocationContext *WithLC = nullptr) const;
+ void printJson(raw_ostream &Out, const ASTContext &Ctx,
+ const LocationContext *LCtx = nullptr, const char *NL = "\n",
+ unsigned int Space = 0, bool IsDot = false) const;
};
class EnvironmentManager {
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=361976&r1=361975&r2=361976&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Wed May 29 08:36:58 2019
@@ -377,9 +377,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,
- const LocationContext *LCtx = nullptr) override;
+ void printState(raw_ostream &Out, ProgramStateRef State,
+ const LocationContext *LCtx, const char *NL,
+ unsigned int Space, bool IsDot) const override;
ProgramStateManager &getStateManager() override { return StateMgr; }
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h?rev=361976&r1=361975&r2=361976&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h Wed May 29 08:36:58 2019
@@ -160,8 +160,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,
- const LocationContext *LCtx = nullptr) = 0;
+ const LocationContext *LCtx, const char *NL,
+ unsigned int Space, bool IsDot) const = 0;
/// Called by CoreEngine when the analysis worklist is either empty or the
// maximum number of analysis steps have been reached.
Modified: cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp?rev=361976&r1=361975&r2=361976&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp (original)
+++ cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp Wed May 29 08:36:58 2019
@@ -30,6 +30,7 @@
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
#include "clang/Analysis/Support/BumpVector.h"
+#include "clang/Basic/JsonSupport.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
@@ -463,17 +464,17 @@ bool LocationContext::isParentOf(const L
return false;
}
-static void printLocation(raw_ostream &OS, const SourceManager &SM,
- SourceLocation SLoc) {
- if (SLoc.isFileID() && SM.isInMainFile(SLoc))
- OS << "line " << SM.getExpansionLineNumber(SLoc);
+static void printLocation(raw_ostream &Out, const SourceManager &SM,
+ SourceLocation Loc) {
+ if (Loc.isFileID() && SM.isInMainFile(Loc))
+ Out << SM.getExpansionLineNumber(Loc);
else
- SLoc.print(OS, SM);
+ Loc.print(Out, SM);
}
-void LocationContext::dumpStack(
- raw_ostream &OS, StringRef Indent, const char *NL, const char *Sep,
- std::function<void(const LocationContext *)> printMoreInfoPerContext) const {
+void LocationContext::dumpStack(raw_ostream &Out, const char *NL,
+ std::function<void(const LocationContext *)>
+ printMoreInfoPerContext) const {
ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
PrintingPolicy PP(Ctx.getLangOpts());
PP.TerseOutput = 1;
@@ -485,38 +486,92 @@ void LocationContext::dumpStack(
for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
switch (LCtx->getKind()) {
case StackFrame:
- OS << Indent << '#' << Frame << ' ';
+ Out << "\t#" << Frame << ' ';
++Frame;
if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
- OS << "Calling " << D->getQualifiedNameAsString();
+ Out << "Calling " << D->getQualifiedNameAsString();
else
- OS << "Calling anonymous code";
+ Out << "Calling anonymous code";
if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
- OS << " at ";
- printLocation(OS, SM, S->getBeginLoc());
+ Out << " at line ";
+ printLocation(Out, SM, S->getBeginLoc());
}
break;
case Scope:
- OS << "Entering scope";
+ Out << "Entering scope";
break;
case Block:
- OS << "Invoking block";
+ Out << "Invoking block";
if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
- OS << " defined at ";
- printLocation(OS, SM, D->getBeginLoc());
+ Out << " defined at line ";
+ printLocation(Out, SM, D->getBeginLoc());
}
break;
}
- OS << NL;
+ Out << NL;
printMoreInfoPerContext(LCtx);
}
}
-LLVM_DUMP_METHOD void LocationContext::dumpStack() const {
- dumpStack(llvm::errs());
+void LocationContext::printJson(raw_ostream &Out, const char *NL,
+ unsigned int Space, bool IsDot,
+ std::function<void(const LocationContext *)>
+ printMoreInfoPerContext) const {
+ ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
+ PrintingPolicy PP(Ctx.getLangOpts());
+ PP.TerseOutput = 1;
+
+ const SourceManager &SM =
+ getAnalysisDeclContext()->getASTContext().getSourceManager();
+
+ unsigned Frame = 0;
+ for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
+ Indent(Out, Space, IsDot) << "{ \"location_context\": \"";
+ switch (LCtx->getKind()) {
+ case StackFrame:
+ Out << '#' << Frame << " Call\", \"calling\": \"";
+ ++Frame;
+ if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
+ Out << D->getQualifiedNameAsString();
+ else
+ Out << "anonymous code";
+
+ Out << "\", \"call_line\": ";
+ if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
+ Out << '\"';
+ printLocation(Out, SM, S->getBeginLoc());
+ Out << '\"';
+ } else {
+ Out << "null";
+ }
+
+ Out << ", \"items\": ";
+ break;
+ case Scope:
+ Out << "Entering scope\" ";
+ break;
+ case Block:
+ Out << "Invoking block\" ";
+ if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
+ Out << ", \"decl_line\": ";
+ printLocation(Out, SM, D->getBeginLoc());
+ Out << ' ';
+ }
+ break;
+ }
+
+ printMoreInfoPerContext(LCtx);
+
+ Out << '}';
+ if (LCtx->getParent())
+ Out << ',';
+ Out << NL;
+ }
}
+LLVM_DUMP_METHOD void LocationContext::dump() const { printJson(llvm::errs()); }
+
//===----------------------------------------------------------------------===//
// Lazily generated map to query the external variables referenced by a Block.
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp?rev=361976&r1=361975&r2=361976&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/Environment.cpp Wed May 29 08:36:58 2019
@@ -18,6 +18,7 @@
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/JsonSupport.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
@@ -199,43 +200,93 @@ EnvironmentManager::removeDeadBindings(E
return NewEnv;
}
-void Environment::print(raw_ostream &Out, const char *NL,
- const char *Sep,
- const ASTContext &Context,
- const LocationContext *WithLC) const {
- if (ExprBindings.isEmpty())
+void Environment::printJson(raw_ostream &Out, const ASTContext &Ctx,
+ const LocationContext *LCtx, const char *NL,
+ unsigned int Space, bool IsDot) const {
+ Indent(Out, Space, IsDot) << "\"environment\": ";
+ ++Space;
+
+ if (ExprBindings.isEmpty()) {
+ Out << "null," << NL;
return;
+ }
- if (!WithLC) {
+ if (!LCtx) {
// Find the freshest location context.
llvm::SmallPtrSet<const LocationContext *, 16> FoundContexts;
- for (auto I : *this) {
+ for (const auto &I : *this) {
const LocationContext *LC = I.first.getLocationContext();
if (FoundContexts.count(LC) == 0) {
// This context is fresher than all other contexts so far.
- WithLC = LC;
+ LCtx = LC;
for (const LocationContext *LCI = LC; LCI; LCI = LCI->getParent())
FoundContexts.insert(LCI);
}
}
}
- assert(WithLC);
+ assert(LCtx);
- PrintingPolicy PP = Context.getPrintingPolicy();
+ Out << '[' << NL; // Start of Environment.
+ PrintingPolicy PP = Ctx.getPrintingPolicy();
- Out << NL << "Expressions by stack frame:" << NL;
- WithLC->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
- for (auto I : ExprBindings) {
- if (I.first.getLocationContext() != LC)
+ LCtx->printJson(Out, NL, Space, IsDot, [&](const LocationContext *LC) {
+ // LCtx items begin
+ bool HasItem = false;
+ unsigned int InnerSpace = Space + 1;
+
+ llvm::SmallString<256> TempBuf;
+ llvm::raw_svector_ostream TempOut(TempBuf);
+
+ // Store the last ExprBinding which we will print.
+ BindingsTy::iterator LastI = ExprBindings.end();
+ for (BindingsTy::iterator I = ExprBindings.begin(); I != ExprBindings.end();
+ ++I) {
+ if (I->first.getLocationContext() != LC)
continue;
- const Stmt *S = I.first.getStmt();
+ if (!HasItem) {
+ HasItem = true;
+ Out << '[' << NL;
+ }
+
+ const Stmt *S = I->first.getStmt();
assert(S != nullptr && "Expected non-null Stmt");
- Out << "(LC" << LC->getID() << ", S" << S->getID(Context) << ") ";
- S->printPretty(Out, /*Helper=*/nullptr, PP);
- Out << " : " << I.second << NL;
+ LastI = I;
+ }
+
+ for (BindingsTy::iterator I = ExprBindings.begin(); I != ExprBindings.end();
+ ++I) {
+ if (I->first.getLocationContext() != LC)
+ continue;
+
+ const Stmt *S = I->first.getStmt();
+ Indent(Out, InnerSpace, IsDot)
+ << "{ \"lctx_id\": " << LC->getID()
+ << ", \"stmt_id\": " << S->getID(Ctx) << ", \"pretty\": ";
+
+ // See whether the current statement is pretty-printable.
+ S->printPretty(TempOut, /*Helper=*/nullptr, PP);
+ if (!TempBuf.empty()) {
+ Out << '\"' << TempBuf.str().trim() << '\"';
+ TempBuf.clear();
+ } else {
+ Out << "null";
+ }
+
+ Out << ", \"value\": \"" << I->second << "\" }";
+
+ if (I != LastI)
+ Out << ',';
+ Out << NL;
}
+
+ if (HasItem)
+ Indent(Out, --InnerSpace, IsDot) << ']';
+ else
+ Out << "null ";
});
+
+ Indent(Out, --Space, IsDot) << "]," << NL; // End of Environment.
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=361976&r1=361975&r2=361976&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed May 29 08:36:58 2019
@@ -558,19 +558,19 @@ static void printObjectsUnderConstructio
}
void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State,
- const char *NL, const char *Sep,
- const LocationContext *LCtx) {
+ const LocationContext *LCtx, const char *NL,
+ unsigned int Space, bool IsDot) const {
if (LCtx) {
if (!State->get<ObjectsUnderConstruction>().isEmpty()) {
- Out << Sep << "Objects under construction:" << NL;
+ Out << "Objects under construction:" << NL;
- LCtx->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
+ LCtx->printJson(Out, NL, Space, IsDot, [&](const LocationContext *LC) {
printObjectsUnderConstructionForContext(Out, State, NL, LC);
});
}
}
- getCheckerManager().runCheckersForPrintState(Out, State, NL, Sep);
+ getCheckerManager().runCheckersForPrintState(Out, State, NL, "");
}
void ExprEngine::processEndWorklist() {
Modified: cfe/trunk/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h?rev=361976&r1=361975&r2=361976&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h Wed May 29 08:36:58 2019
@@ -32,9 +32,9 @@ public:
assert(LCtx);
}
- void print(raw_ostream &OS) const override {
- OS << "While analyzing stack: \n";
- LCtx->dumpStack(OS, "\t");
+ void print(raw_ostream &Out) const override {
+ Out << "While analyzing stack: \n";
+ LCtx->dumpStack(Out);
}
};
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=361976&r1=361975&r2=361976&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Wed May 29 08:36:58 2019
@@ -449,7 +449,7 @@ void ProgramState::printJson(raw_ostream
Mgr.getStoreManager().printJson(Out, getStore(), NL, Space, IsDot);
// Print out the environment.
- Env.print(Out, NL, Sep, Context, LCtx);
+ Env.printJson(Out, Context, LCtx, NL, Space, IsDot);
// Print out the constraints.
Mgr.getConstraintManager().print(this, Out, NL, Sep);
@@ -458,7 +458,7 @@ void ProgramState::printJson(raw_ostream
printDynamicTypeInfo(this, Out, NL, Sep);
// Print checker-specific data.
- Mgr.getOwningEngine().printState(Out, this, NL, Sep, LCtx);
+ Mgr.getOwningEngine().printState(Out, this, LCtx, NL, Space, IsDot);
}
void ProgramState::printDOT(raw_ostream &Out, const LocationContext *LCtx,
Modified: cfe/trunk/test/Analysis/expr-inspection.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/expr-inspection.c?rev=361976&r1=361975&r2=361976&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/expr-inspection.c (original)
+++ cfe/trunk/test/Analysis/expr-inspection.c Wed May 29 08:36:58 2019
@@ -27,11 +27,12 @@ void foo(int x) {
// CHECK-NEXT: { "cluster": "y", "items": [
// CHECK-NEXT: { "kind": "Direct", "offset": 0, "value": "2 S32b" }
// CHECK-NEXT: ]}
-// CHECK-NEXT: ]
-
-// CHECK: Expressions by stack frame:
-// CHECK-NEXT: #0 Calling foo
-// CHECK-NEXT: (LC1, S847) clang_analyzer_printState : &code{clang_analyzer_printState}
+// CHECK-NEXT: ],
+// CHECK-NEXT: "environment": [
+// CHECK-NEXT: { "location_context": "#0 Call", "calling": "foo", "call_line": null, "items": [
+// CHECK-NEXT: { "lctx_id": 1, "stmt_id": 847, "pretty": "clang_analyzer_printState", "value": "&code{clang_analyzer_printState}" }
+// CHECK-NEXT: ]}
+// CHECK-NEXT: ],
// CHECK: Ranges of symbol values:
// CHECK-NEXT: reg_$0<int x> : { [-2147483648, 13] }
More information about the cfe-commits
mailing list