summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h10
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp4
-rw-r--r--clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp44
-rw-r--r--clang/lib/StaticAnalyzer/Core/ProgramState.cpp2
-rw-r--r--clang/test/Analysis/expr-inspection.c2
5 files changed, 37 insertions, 25 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
index 6608f26b3b3..a84b2487206 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
@@ -29,12 +29,11 @@ class MemRegion;
/// symbol to its most likely type.
struct DynamicTypeMap {};
-using DynamicTypeMapImpl =
- llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>;
+using DynamicTypeMapTy = llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>;
template <>
struct ProgramStateTrait<DynamicTypeMap>
- : public ProgramStatePartialTrait<DynamicTypeMapImpl> {
+ : public ProgramStatePartialTrait<DynamicTypeMapTy> {
static void *GDMIndex();
};
@@ -54,8 +53,9 @@ inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State,
DynamicTypeInfo(NewTy, CanBeSubClassed));
}
-void printDynamicTypeInfo(ProgramStateRef State, raw_ostream &Out,
- const char *NL, const char *Sep);
+void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State,
+ const char *NL = "\n", unsigned int Space = 0,
+ bool IsDot = false);
} // namespace ento
} // namespace clang
diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
index 1862ffc79d4..916a20e559f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
@@ -114,8 +114,8 @@ public:
void DynamicTypePropagation::checkDeadSymbols(SymbolReaper &SR,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
- DynamicTypeMapImpl TypeMap = State->get<DynamicTypeMap>();
- for (DynamicTypeMapImpl::iterator I = TypeMap.begin(), E = TypeMap.end();
+ DynamicTypeMapTy TypeMap = State->get<DynamicTypeMap>();
+ for (DynamicTypeMapTy::iterator I = TypeMap.begin(), E = TypeMap.end();
I != E; ++I) {
if (!SR.isLiveRegion(I->first)) {
State = State->remove<DynamicTypeMap>(I->first);
diff --git a/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp b/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
index c5ee8ce4c22..22c4cc4a624 100644
--- a/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
+++ b/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+#include "clang/Basic/JsonSupport.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
@@ -53,27 +54,38 @@ ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
return NewState;
}
-void printDynamicTypeInfo(ProgramStateRef State, raw_ostream &Out,
- const char *NL, const char *Sep) {
- bool First = true;
- for (const auto &I : State->get<DynamicTypeMap>()) {
- if (First) {
- Out << NL << "Dynamic types of regions:" << NL;
- First = false;
- }
- const MemRegion *MR = I.first;
- const DynamicTypeInfo &DTI = I.second;
- Out << MR << " : ";
+void printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State,
+ const char *NL, unsigned int Space, bool IsDot) {
+ Indent(Out, Space, IsDot) << "\"dynamic_types\": ";
+
+ const DynamicTypeMapTy &DTM = State->get<DynamicTypeMap>();
+ if (DTM.isEmpty()) {
+ Out << "null," << NL;
+ return;
+ }
+
+ ++Space;
+ Out << '[' << NL;
+ for (DynamicTypeMapTy::iterator I = DTM.begin(); I != DTM.end(); ++I) {
+ const MemRegion *MR = I->first;
+ const DynamicTypeInfo &DTI = I->second;
+ Out << "{ \"region\": \"" << MR << "\", \"dyn_type\": ";
if (DTI.isValid()) {
- Out << DTI.getType()->getPointeeType().getAsString();
- if (DTI.canBeASubClass()) {
- Out << " (or its subclass)";
- }
+ Out << '\"' << DTI.getType()->getPointeeType().getAsString()
+ << "\" \"sub_classable\": "
+ << (DTI.canBeASubClass() ? "true" : "false");
} else {
- Out << "Invalid type info";
+ Out << "null"; // Invalid type info
}
+ Out << "\" }";
+
+ if (std::next(I) != DTM.end())
+ Out << ',';
Out << NL;
}
+
+ --Space;
+ Indent(Out, Space, IsDot) << "]," << NL;
}
void *ProgramStateTrait<DynamicTypeMap>::GDMIndex() {
diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
index 090801f1abb..b661dd1de08 100644
--- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -455,7 +455,7 @@ void ProgramState::printJson(raw_ostream &Out, const LocationContext *LCtx,
Mgr.getConstraintManager().printJson(Out, this, NL, Space, IsDot);
// Print out the tracked dynamic types.
- printDynamicTypeInfo(this, Out, NL, Sep);
+ printDynamicTypeInfoJson(Out, this, NL, Space, IsDot);
// Print checker-specific data.
Mgr.getOwningEngine().printState(Out, this, LCtx, NL, Space, IsDot);
diff --git a/clang/test/Analysis/expr-inspection.c b/clang/test/Analysis/expr-inspection.c
index 461252d5372..abfef06b997 100644
--- a/clang/test/Analysis/expr-inspection.c
+++ b/clang/test/Analysis/expr-inspection.c
@@ -36,4 +36,4 @@ void foo(int x) {
// CHECK-NEXT: "constraints": [
// CHECK-NEXT: { "symbol": "reg_$0<int x>", "range": "{ [-2147483648, 13] }" }
// CHECK-NEXT: ],
-
+// CHECK-NEXT: "dynamic_types": null,
OpenPOWER on IntegriCloud