Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h @@ -29,12 +29,11 @@ /// symbol to its most likely type. struct DynamicTypeMap {}; -using DynamicTypeMapImpl = - llvm::ImmutableMap; +using DynamicTypeMapTy = llvm::ImmutableMap; template <> struct ProgramStateTrait - : public ProgramStatePartialTrait { + : public ProgramStatePartialTrait { static void *GDMIndex(); }; @@ -54,8 +53,9 @@ DynamicTypeInfo(NewTy, CanBeSubClassed)); } -void printDynamicTypeInfo(ProgramStateRef State, raw_ostream &Out, - const char *NL, const char *Sep); +void printDynamicTypeInfo(raw_ostream &Out, ProgramStateRef State, + const char *NL = "\n", const char *Sep = "", + unsigned int Space = 0); } // namespace ento } // namespace clang Index: clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -114,8 +114,8 @@ void DynamicTypePropagation::checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const { ProgramStateRef State = C.getState(); - DynamicTypeMapImpl TypeMap = State->get(); - for (DynamicTypeMapImpl::iterator I = TypeMap.begin(), E = TypeMap.end(); + DynamicTypeMapTy TypeMap = State->get(); + for (DynamicTypeMapTy::iterator I = TypeMap.begin(), E = TypeMap.end(); I != E; ++I) { if (!SR.isLiveRegion(I->first)) { State = State->remove(I->first); Index: clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp +++ 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,34 @@ return NewState; } -void printDynamicTypeInfo(ProgramStateRef State, raw_ostream &Out, - const char *NL, const char *Sep) { - bool First = true; - for (const auto &I : State->get()) { - if (First) { - Out << NL << "Dynamic types of regions:" << NL; - First = false; - } +void printDynamicTypeInfo(raw_ostream &Out, ProgramStateRef State, + const char *NL, const char *Sep, unsigned int Space) { + Indent(Out, Space) + << "\"dynamic_types\": { \"title\": \"Dynamic types\", \"items\": "; + + const DynamicTypeMapTy &DTM = State->get(); + if (DTM.isEmpty()) { + Out << "null }," << NL; + return; + } + + ++Space; + Out << '[' << NL; + for (const auto &I : DTM) { const MemRegion *MR = I.first; const DynamicTypeInfo &DTI = I.second; - Out << MR << " : "; + 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 << NL; + Out << "\" }," << NL; } + --Space; + Indent(Out, Space) << "]}," << NL; } void *ProgramStateTrait::GDMIndex() { Index: clang/lib/StaticAnalyzer/Core/ProgramState.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -455,7 +455,7 @@ Mgr.getConstraintManager().print(Out, this, NL, Sep, Space); // Print out the tracked dynamic types. - printDynamicTypeInfo(this, Out, NL, Sep); + printDynamicTypeInfo(Out, this, NL, Sep, Space); // Print checker-specific data. Mgr.getOwningEngine().printState(Out, this, LCtx, NL, Sep, Space); Index: clang/test/Analysis/expr-inspection.c =================================================================== --- clang/test/Analysis/expr-inspection.c +++ clang/test/Analysis/expr-inspection.c @@ -35,5 +35,5 @@ // CHECK-NEXT: ]}, // CHECK-NEXT: "constraints": { "title": "Constraints", "items": [ // CHECK-NEXT: { "name": "reg_$0", "value": "{ [-2147483648, 13] }" }, -// CHECK-NEXT: ]} - +// CHECK-NEXT: ]}, +// CHECK-NEXT: "dynamic_types": { "title": "Dynamic types", "items": null },