Index: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h +++ cfe/trunk/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 printDynamicTypeInfoJson(raw_ostream &Out, ProgramStateRef State, + const char *NL = "\n", unsigned int Space = 0, + bool IsDot = false); } // namespace ento } // namespace clang Index: cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp +++ cfe/trunk/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 @@ 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; - } - 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(); + 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::GDMIndex() { Index: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -455,7 +455,7 @@ 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); Index: cfe/trunk/test/Analysis/expr-inspection.c =================================================================== --- cfe/trunk/test/Analysis/expr-inspection.c +++ cfe/trunk/test/Analysis/expr-inspection.c @@ -36,4 +36,4 @@ // CHECK-NEXT: "constraints": [ // CHECK-NEXT: { "symbol": "reg_$0", "range": "{ [-2147483648, 13] }" } // CHECK-NEXT: ], - +// CHECK-NEXT: "dynamic_types": null,