summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Core/Environment.cpp87
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp10
-rw-r--r--clang/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h6
-rw-r--r--clang/lib/StaticAnalyzer/Core/ProgramState.cpp4
4 files changed, 79 insertions, 28 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/Environment.cpp b/clang/lib/StaticAnalyzer/Core/Environment.cpp
index 9d888ece177..6344bc5a4d6 100644
--- a/clang/lib/StaticAnalyzer/Core/Environment.cpp
+++ b/clang/lib/StaticAnalyzer/Core/Environment.cpp
@@ -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(Environment Env,
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);
+
+ Out << '[' << NL; // Start of Environment.
+ PrintingPolicy PP = Ctx.getPrintingPolicy();
+
+ LCtx->printJson(Out, NL, Space, IsDot, [&](const LocationContext *LC) {
+ // LCtx items begin
+ bool HasItem = false;
+ unsigned int InnerSpace = Space + 1;
- PrintingPolicy PP = Context.getPrintingPolicy();
+ llvm::SmallString<256> TempBuf;
+ llvm::raw_svector_ostream TempOut(TempBuf);
- Out << NL << "Expressions by stack frame:" << NL;
- WithLC->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
- for (auto I : ExprBindings) {
- if (I.first.getLocationContext() != LC)
+ // 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.
}
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 975af474392..a57546b8909 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -558,19 +558,19 @@ static void printObjectsUnderConstructionForContext(raw_ostream &Out,
}
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() {
diff --git a/clang/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h b/clang/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h
index c79273dca80..c71ee3bd428 100644
--- a/clang/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h
+++ b/clang/lib/StaticAnalyzer/Core/PrettyStackTraceLocationContext.h
@@ -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);
}
};
diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
index f5c7af3b1c2..911b96db2c9 100644
--- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -449,7 +449,7 @@ void ProgramState::printJson(raw_ostream &Out, const LocationContext *LCtx,
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 &Out, const LocationContext *LCtx,
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,
OpenPOWER on IntegriCloud