summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/StaticAnalyzer/Core/CheckerManager.cpp73
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp3
2 files changed, 70 insertions, 6 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 53d872021af..cda9fe9bf5c 100644
--- a/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/DeclBase.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/ProgramPoint.h"
+#include "clang/Basic/JsonSupport.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
@@ -698,11 +699,73 @@ void CheckerManager::runCheckersOnEndOfTranslationUnit(
EndOfTranslationUnitChecker(TU, mgr, BR);
}
-void CheckerManager::runCheckersForPrintState(raw_ostream &Out,
- ProgramStateRef State,
- const char *NL, const char *Sep) {
- for (const auto &CheckerTag : CheckerTags)
- CheckerTag.second->printState(Out, State, NL, Sep);
+void CheckerManager::runCheckersForPrintStateJson(raw_ostream &Out,
+ ProgramStateRef State,
+ const char *NL,
+ unsigned int Space,
+ bool IsDot) const {
+ Indent(Out, Space, IsDot) << "\"checker_messages\": ";
+
+ // Create a temporary stream to see whether we have any message.
+ SmallString<1024> TempBuf;
+ llvm::raw_svector_ostream TempOut(TempBuf);
+ unsigned int InnerSpace = Space + 2;
+
+ // Create the new-line in JSON with enough space.
+ SmallString<128> NewLine;
+ llvm::raw_svector_ostream NLOut(NewLine);
+ NLOut << "\", " << NL; // Inject the ending and a new line
+ Indent(NLOut, InnerSpace, IsDot) << "\""; // then begin the next message.
+
+ ++Space;
+ bool HasMessage = false;
+
+ // Store the last CheckerTag.
+ const void *LastCT = nullptr;
+ for (const auto &CT : CheckerTags) {
+ // See whether the current checker has a message.
+ CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
+
+ if (TempBuf.empty())
+ continue;
+
+ if (!HasMessage) {
+ Out << '[' << NL;
+ HasMessage = true;
+ }
+
+ LastCT = &CT;
+ TempBuf.clear();
+ }
+
+ for (const auto &CT : CheckerTags) {
+ // See whether the current checker has a message.
+ CT.second->printState(TempOut, State, /*NL=*/NewLine.c_str(), /*Sep=*/"");
+
+ if (TempBuf.empty())
+ continue;
+
+ Indent(Out, Space, IsDot)
+ << "{ \"checker\": \"" << CT.second->getCheckName().getName()
+ << "\", \"messages\": [" << NL;
+ Indent(Out, InnerSpace, IsDot)
+ << '\"' << TempBuf.str().trim() << '\"' << NL;
+ Indent(Out, Space, IsDot) << "]}";
+
+ if (&CT != LastCT)
+ Out << ',';
+ Out << NL;
+
+ TempBuf.clear();
+ }
+
+ // It is the last element of the 'program_state' so do not add a comma.
+ if (HasMessage)
+ Indent(Out, --Space, IsDot) << "]";
+ else
+ Out << "null";
+
+ Out << NL;
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 07fc6f7643a..6fa7cf2e232 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -633,7 +633,8 @@ void ExprEngine::printJson(raw_ostream &Out, ProgramStateRef State,
Out << "null," << NL;
}
- getCheckerManager().runCheckersForPrintState(Out, State, NL, "");
+ getCheckerManager().runCheckersForPrintStateJson(Out, State, NL, Space,
+ IsDot);
}
void ExprEngine::processEndWorklist() {
OpenPOWER on IntegriCloud