1351280Sdim//===--- JSONNodeDumper.h - Printing of AST nodes to JSON -----------------===// 2351280Sdim// 3351280Sdim// The LLVM Compiler Infrastructure 4351280Sdim// 5351280Sdim// This file is distributed under the University of Illinois Open Source 6351280Sdim// License. See LICENSE.TXT for details. 7351280Sdim// 8351280Sdim//===----------------------------------------------------------------------===// 9351280Sdim// 10351280Sdim// This file implements AST dumping of components of individual AST nodes to 11351280Sdim// a JSON. 12351280Sdim// 13351280Sdim//===----------------------------------------------------------------------===// 14351280Sdim 15351280Sdim#ifndef LLVM_CLANG_AST_JSONNODEDUMPER_H 16351280Sdim#define LLVM_CLANG_AST_JSONNODEDUMPER_H 17351280Sdim 18351280Sdim#include "clang/AST/ASTContext.h" 19360784Sdim#include "clang/AST/ASTDumperUtils.h" 20351280Sdim#include "clang/AST/ASTNodeTraverser.h" 21351280Sdim#include "clang/AST/AttrVisitor.h" 22351280Sdim#include "clang/AST/CommentCommandTraits.h" 23351280Sdim#include "clang/AST/CommentVisitor.h" 24351280Sdim#include "clang/AST/ExprCXX.h" 25360784Sdim#include "clang/AST/Mangle.h" 26351280Sdim#include "llvm/Support/JSON.h" 27351280Sdim 28351280Sdimnamespace clang { 29351280Sdim 30351280Sdimclass NodeStreamer { 31351280Sdim bool FirstChild = true; 32351280Sdim bool TopLevel = true; 33351280Sdim llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending; 34351280Sdim 35351280Sdimprotected: 36351280Sdim llvm::json::OStream JOS; 37351280Sdim 38351280Sdimpublic: 39351280Sdim /// Add a child of the current node. Calls DoAddChild without arguments 40351280Sdim template <typename Fn> void AddChild(Fn DoAddChild) { 41351280Sdim return AddChild("", DoAddChild); 42351280Sdim } 43351280Sdim 44351280Sdim /// Add a child of the current node with an optional label. 45351280Sdim /// Calls DoAddChild without arguments. 46351280Sdim template <typename Fn> void AddChild(StringRef Label, Fn DoAddChild) { 47351280Sdim // If we're at the top level, there's nothing interesting to do; just 48351280Sdim // run the dumper. 49351280Sdim if (TopLevel) { 50351280Sdim TopLevel = false; 51351280Sdim JOS.objectBegin(); 52351280Sdim 53351280Sdim DoAddChild(); 54351280Sdim 55351280Sdim while (!Pending.empty()) { 56351280Sdim Pending.back()(true); 57351280Sdim Pending.pop_back(); 58351280Sdim } 59351280Sdim 60351280Sdim JOS.objectEnd(); 61351280Sdim TopLevel = true; 62351280Sdim return; 63351280Sdim } 64351280Sdim 65351280Sdim // We need to capture an owning-string in the lambda because the lambda 66351280Sdim // is invoked in a deferred manner. 67351280Sdim std::string LabelStr = !Label.empty() ? Label : "inner"; 68351280Sdim bool WasFirstChild = FirstChild; 69351280Sdim auto DumpWithIndent = [=](bool IsLastChild) { 70351280Sdim if (WasFirstChild) { 71351280Sdim JOS.attributeBegin(LabelStr); 72351280Sdim JOS.arrayBegin(); 73351280Sdim } 74351280Sdim 75351280Sdim FirstChild = true; 76351280Sdim unsigned Depth = Pending.size(); 77351280Sdim JOS.objectBegin(); 78351280Sdim 79351280Sdim DoAddChild(); 80351280Sdim 81351280Sdim // If any children are left, they're the last at their nesting level. 82351280Sdim // Dump those ones out now. 83351280Sdim while (Depth < Pending.size()) { 84351280Sdim Pending.back()(true); 85351280Sdim this->Pending.pop_back(); 86351280Sdim } 87351280Sdim 88351280Sdim JOS.objectEnd(); 89351280Sdim 90351280Sdim if (IsLastChild) { 91351280Sdim JOS.arrayEnd(); 92351280Sdim JOS.attributeEnd(); 93351280Sdim } 94351280Sdim }; 95351280Sdim 96351280Sdim if (FirstChild) { 97351280Sdim Pending.push_back(std::move(DumpWithIndent)); 98351280Sdim } else { 99351280Sdim Pending.back()(false); 100351280Sdim Pending.back() = std::move(DumpWithIndent); 101351280Sdim } 102351280Sdim FirstChild = false; 103351280Sdim } 104351280Sdim 105351280Sdim NodeStreamer(raw_ostream &OS) : JOS(OS, 2) {} 106351280Sdim}; 107351280Sdim 108351280Sdim// Dumps AST nodes in JSON format. There is no implied stability for the 109351280Sdim// content or format of the dump between major releases of Clang, other than it 110351280Sdim// being valid JSON output. Further, there is no requirement that the 111351280Sdim// information dumped is a complete representation of the AST, only that the 112351280Sdim// information presented is correct. 113351280Sdimclass JSONNodeDumper 114351280Sdim : public ConstAttrVisitor<JSONNodeDumper>, 115351280Sdim public comments::ConstCommentVisitor<JSONNodeDumper, void, 116351280Sdim const comments::FullComment *>, 117351280Sdim public ConstTemplateArgumentVisitor<JSONNodeDumper>, 118351280Sdim public ConstStmtVisitor<JSONNodeDumper>, 119351280Sdim public TypeVisitor<JSONNodeDumper>, 120351280Sdim public ConstDeclVisitor<JSONNodeDumper>, 121351280Sdim public NodeStreamer { 122351280Sdim friend class JSONDumper; 123351280Sdim 124351280Sdim const SourceManager &SM; 125351280Sdim ASTContext& Ctx; 126360784Sdim ASTNameGenerator ASTNameGen; 127351280Sdim PrintingPolicy PrintPolicy; 128351280Sdim const comments::CommandTraits *Traits; 129360784Sdim StringRef LastLocFilename, LastLocPresumedFilename; 130351280Sdim unsigned LastLocLine, LastLocPresumedLine; 131351280Sdim 132351280Sdim using InnerAttrVisitor = ConstAttrVisitor<JSONNodeDumper>; 133351280Sdim using InnerCommentVisitor = 134351280Sdim comments::ConstCommentVisitor<JSONNodeDumper, void, 135351280Sdim const comments::FullComment *>; 136351280Sdim using InnerTemplateArgVisitor = ConstTemplateArgumentVisitor<JSONNodeDumper>; 137351280Sdim using InnerStmtVisitor = ConstStmtVisitor<JSONNodeDumper>; 138351280Sdim using InnerTypeVisitor = TypeVisitor<JSONNodeDumper>; 139351280Sdim using InnerDeclVisitor = ConstDeclVisitor<JSONNodeDumper>; 140351280Sdim 141351280Sdim void attributeOnlyIfTrue(StringRef Key, bool Value) { 142351280Sdim if (Value) 143351280Sdim JOS.attribute(Key, Value); 144351280Sdim } 145351280Sdim 146360784Sdim void writeIncludeStack(PresumedLoc Loc, bool JustFirst = false); 147360784Sdim 148351280Sdim // Writes the attributes of a SourceLocation object without. 149351280Sdim void writeBareSourceLocation(SourceLocation Loc, bool IsSpelling); 150351280Sdim 151351280Sdim // Writes the attributes of a SourceLocation to JSON based on its presumed 152351280Sdim // spelling location. If the given location represents a macro invocation, 153351280Sdim // this outputs two sub-objects: one for the spelling and one for the 154351280Sdim // expansion location. 155351280Sdim void writeSourceLocation(SourceLocation Loc); 156351280Sdim void writeSourceRange(SourceRange R); 157351280Sdim std::string createPointerRepresentation(const void *Ptr); 158351280Sdim llvm::json::Object createQualType(QualType QT, bool Desugar = true); 159351280Sdim llvm::json::Object createBareDeclRef(const Decl *D); 160351280Sdim void writeBareDeclRef(const Decl *D); 161351280Sdim llvm::json::Object createCXXRecordDefinitionData(const CXXRecordDecl *RD); 162351280Sdim llvm::json::Object createCXXBaseSpecifier(const CXXBaseSpecifier &BS); 163351280Sdim std::string createAccessSpecifier(AccessSpecifier AS); 164351280Sdim llvm::json::Array createCastPath(const CastExpr *C); 165351280Sdim 166351280Sdim void writePreviousDeclImpl(...) {} 167351280Sdim 168351280Sdim template <typename T> void writePreviousDeclImpl(const Mergeable<T> *D) { 169351280Sdim const T *First = D->getFirstDecl(); 170351280Sdim if (First != D) 171351280Sdim JOS.attribute("firstRedecl", createPointerRepresentation(First)); 172351280Sdim } 173351280Sdim 174351280Sdim template <typename T> void writePreviousDeclImpl(const Redeclarable<T> *D) { 175351280Sdim const T *Prev = D->getPreviousDecl(); 176351280Sdim if (Prev) 177351280Sdim JOS.attribute("previousDecl", createPointerRepresentation(Prev)); 178351280Sdim } 179351280Sdim void addPreviousDeclaration(const Decl *D); 180351280Sdim 181351280Sdim StringRef getCommentCommandName(unsigned CommandID) const; 182351280Sdim 183351280Sdimpublic: 184351280Sdim JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx, 185351280Sdim const PrintingPolicy &PrintPolicy, 186351280Sdim const comments::CommandTraits *Traits) 187360784Sdim : NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), ASTNameGen(Ctx), 188360784Sdim PrintPolicy(PrintPolicy), Traits(Traits), LastLocLine(0), 189360784Sdim LastLocPresumedLine(0) {} 190351280Sdim 191351280Sdim void Visit(const Attr *A); 192351280Sdim void Visit(const Stmt *Node); 193351280Sdim void Visit(const Type *T); 194351280Sdim void Visit(QualType T); 195351280Sdim void Visit(const Decl *D); 196351280Sdim 197351280Sdim void Visit(const comments::Comment *C, const comments::FullComment *FC); 198351280Sdim void Visit(const TemplateArgument &TA, SourceRange R = {}, 199351280Sdim const Decl *From = nullptr, StringRef Label = {}); 200351280Sdim void Visit(const CXXCtorInitializer *Init); 201351280Sdim void Visit(const OMPClause *C); 202351280Sdim void Visit(const BlockDecl::Capture &C); 203351280Sdim void Visit(const GenericSelectionExpr::ConstAssociation &A); 204351280Sdim 205351280Sdim void VisitTypedefType(const TypedefType *TT); 206351280Sdim void VisitFunctionType(const FunctionType *T); 207351280Sdim void VisitFunctionProtoType(const FunctionProtoType *T); 208351280Sdim void VisitRValueReferenceType(const ReferenceType *RT); 209351280Sdim void VisitArrayType(const ArrayType *AT); 210351280Sdim void VisitConstantArrayType(const ConstantArrayType *CAT); 211351280Sdim void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *VT); 212351280Sdim void VisitVectorType(const VectorType *VT); 213351280Sdim void VisitUnresolvedUsingType(const UnresolvedUsingType *UUT); 214351280Sdim void VisitUnaryTransformType(const UnaryTransformType *UTT); 215351280Sdim void VisitTagType(const TagType *TT); 216351280Sdim void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT); 217351280Sdim void VisitAutoType(const AutoType *AT); 218351280Sdim void VisitTemplateSpecializationType(const TemplateSpecializationType *TST); 219351280Sdim void VisitInjectedClassNameType(const InjectedClassNameType *ICNT); 220351280Sdim void VisitObjCInterfaceType(const ObjCInterfaceType *OIT); 221351280Sdim void VisitPackExpansionType(const PackExpansionType *PET); 222351280Sdim void VisitElaboratedType(const ElaboratedType *ET); 223351280Sdim void VisitMacroQualifiedType(const MacroQualifiedType *MQT); 224351280Sdim void VisitMemberPointerType(const MemberPointerType *MPT); 225351280Sdim 226351280Sdim void VisitNamedDecl(const NamedDecl *ND); 227351280Sdim void VisitTypedefDecl(const TypedefDecl *TD); 228351280Sdim void VisitTypeAliasDecl(const TypeAliasDecl *TAD); 229351280Sdim void VisitNamespaceDecl(const NamespaceDecl *ND); 230351280Sdim void VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD); 231351280Sdim void VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD); 232351280Sdim void VisitUsingDecl(const UsingDecl *UD); 233351280Sdim void VisitUsingShadowDecl(const UsingShadowDecl *USD); 234351280Sdim void VisitVarDecl(const VarDecl *VD); 235351280Sdim void VisitFieldDecl(const FieldDecl *FD); 236351280Sdim void VisitFunctionDecl(const FunctionDecl *FD); 237351280Sdim void VisitEnumDecl(const EnumDecl *ED); 238351280Sdim void VisitEnumConstantDecl(const EnumConstantDecl *ECD); 239351280Sdim void VisitRecordDecl(const RecordDecl *RD); 240351280Sdim void VisitCXXRecordDecl(const CXXRecordDecl *RD); 241351280Sdim void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); 242351280Sdim void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); 243351280Sdim void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); 244351280Sdim void VisitLinkageSpecDecl(const LinkageSpecDecl *LSD); 245351280Sdim void VisitAccessSpecDecl(const AccessSpecDecl *ASD); 246351280Sdim void VisitFriendDecl(const FriendDecl *FD); 247351280Sdim 248351280Sdim void VisitObjCIvarDecl(const ObjCIvarDecl *D); 249351280Sdim void VisitObjCMethodDecl(const ObjCMethodDecl *D); 250351280Sdim void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D); 251351280Sdim void VisitObjCCategoryDecl(const ObjCCategoryDecl *D); 252351280Sdim void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D); 253351280Sdim void VisitObjCProtocolDecl(const ObjCProtocolDecl *D); 254351280Sdim void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D); 255351280Sdim void VisitObjCImplementationDecl(const ObjCImplementationDecl *D); 256351280Sdim void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D); 257351280Sdim void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); 258351280Sdim void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); 259351280Sdim void VisitBlockDecl(const BlockDecl *D); 260351280Sdim 261351280Sdim void VisitDeclRefExpr(const DeclRefExpr *DRE); 262351280Sdim void VisitPredefinedExpr(const PredefinedExpr *PE); 263351280Sdim void VisitUnaryOperator(const UnaryOperator *UO); 264351280Sdim void VisitBinaryOperator(const BinaryOperator *BO); 265351280Sdim void VisitCompoundAssignOperator(const CompoundAssignOperator *CAO); 266351280Sdim void VisitMemberExpr(const MemberExpr *ME); 267351280Sdim void VisitCXXNewExpr(const CXXNewExpr *NE); 268351280Sdim void VisitCXXDeleteExpr(const CXXDeleteExpr *DE); 269351280Sdim void VisitCXXThisExpr(const CXXThisExpr *TE); 270351280Sdim void VisitCastExpr(const CastExpr *CE); 271351280Sdim void VisitImplicitCastExpr(const ImplicitCastExpr *ICE); 272351280Sdim void VisitCallExpr(const CallExpr *CE); 273351280Sdim void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *TTE); 274351280Sdim void VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE); 275351280Sdim void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *ULE); 276351280Sdim void VisitAddrLabelExpr(const AddrLabelExpr *ALE); 277351280Sdim void VisitCXXTypeidExpr(const CXXTypeidExpr *CTE); 278351280Sdim void VisitConstantExpr(const ConstantExpr *CE); 279351280Sdim void VisitInitListExpr(const InitListExpr *ILE); 280351280Sdim void VisitGenericSelectionExpr(const GenericSelectionExpr *GSE); 281351280Sdim void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *UCE); 282351280Sdim void VisitCXXConstructExpr(const CXXConstructExpr *CE); 283351280Sdim void VisitExprWithCleanups(const ExprWithCleanups *EWC); 284351280Sdim void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE); 285351280Sdim void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE); 286351280Sdim void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *ME); 287351280Sdim 288351280Sdim void VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE); 289351280Sdim void VisitObjCMessageExpr(const ObjCMessageExpr *OME); 290351280Sdim void VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE); 291351280Sdim void VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE); 292351280Sdim void VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE); 293351280Sdim void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE); 294351280Sdim void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *OSRE); 295351280Sdim void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE); 296351280Sdim void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE); 297351280Sdim 298351280Sdim void VisitIntegerLiteral(const IntegerLiteral *IL); 299351280Sdim void VisitCharacterLiteral(const CharacterLiteral *CL); 300351280Sdim void VisitFixedPointLiteral(const FixedPointLiteral *FPL); 301351280Sdim void VisitFloatingLiteral(const FloatingLiteral *FL); 302351280Sdim void VisitStringLiteral(const StringLiteral *SL); 303351280Sdim void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE); 304351280Sdim 305351280Sdim void VisitIfStmt(const IfStmt *IS); 306351280Sdim void VisitSwitchStmt(const SwitchStmt *SS); 307351280Sdim void VisitCaseStmt(const CaseStmt *CS); 308351280Sdim void VisitLabelStmt(const LabelStmt *LS); 309351280Sdim void VisitGotoStmt(const GotoStmt *GS); 310351280Sdim void VisitWhileStmt(const WhileStmt *WS); 311351280Sdim void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *OACS); 312351280Sdim 313351280Sdim void VisitNullTemplateArgument(const TemplateArgument &TA); 314351280Sdim void VisitTypeTemplateArgument(const TemplateArgument &TA); 315351280Sdim void VisitDeclarationTemplateArgument(const TemplateArgument &TA); 316351280Sdim void VisitNullPtrTemplateArgument(const TemplateArgument &TA); 317351280Sdim void VisitIntegralTemplateArgument(const TemplateArgument &TA); 318351280Sdim void VisitTemplateTemplateArgument(const TemplateArgument &TA); 319351280Sdim void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA); 320351280Sdim void VisitExpressionTemplateArgument(const TemplateArgument &TA); 321351280Sdim void VisitPackTemplateArgument(const TemplateArgument &TA); 322351280Sdim 323351280Sdim void visitTextComment(const comments::TextComment *C, 324351280Sdim const comments::FullComment *); 325351280Sdim void visitInlineCommandComment(const comments::InlineCommandComment *C, 326351280Sdim const comments::FullComment *); 327351280Sdim void visitHTMLStartTagComment(const comments::HTMLStartTagComment *C, 328351280Sdim const comments::FullComment *); 329351280Sdim void visitHTMLEndTagComment(const comments::HTMLEndTagComment *C, 330351280Sdim const comments::FullComment *); 331351280Sdim void visitBlockCommandComment(const comments::BlockCommandComment *C, 332351280Sdim const comments::FullComment *); 333351280Sdim void visitParamCommandComment(const comments::ParamCommandComment *C, 334351280Sdim const comments::FullComment *FC); 335351280Sdim void visitTParamCommandComment(const comments::TParamCommandComment *C, 336351280Sdim const comments::FullComment *FC); 337351280Sdim void visitVerbatimBlockComment(const comments::VerbatimBlockComment *C, 338351280Sdim const comments::FullComment *); 339351280Sdim void 340351280Sdim visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment *C, 341351280Sdim const comments::FullComment *); 342351280Sdim void visitVerbatimLineComment(const comments::VerbatimLineComment *C, 343351280Sdim const comments::FullComment *); 344351280Sdim}; 345351280Sdim 346351280Sdimclass JSONDumper : public ASTNodeTraverser<JSONDumper, JSONNodeDumper> { 347351280Sdim JSONNodeDumper NodeDumper; 348351280Sdim 349351280Sdim template <typename SpecializationDecl> 350351280Sdim void writeTemplateDeclSpecialization(const SpecializationDecl *SD, 351351280Sdim bool DumpExplicitInst, 352351280Sdim bool DumpRefOnly) { 353351280Sdim bool DumpedAny = false; 354351280Sdim for (const auto *RedeclWithBadType : SD->redecls()) { 355351280Sdim // FIXME: The redecls() range sometimes has elements of a less-specific 356351280Sdim // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives 357351280Sdim // us TagDecls, and should give CXXRecordDecls). 358351280Sdim const auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType); 359351280Sdim if (!Redecl) { 360351280Sdim // Found the injected-class-name for a class template. This will be 361351280Sdim // dumped as part of its surrounding class so we don't need to dump it 362351280Sdim // here. 363351280Sdim assert(isa<CXXRecordDecl>(RedeclWithBadType) && 364351280Sdim "expected an injected-class-name"); 365351280Sdim continue; 366351280Sdim } 367351280Sdim 368351280Sdim switch (Redecl->getTemplateSpecializationKind()) { 369351280Sdim case TSK_ExplicitInstantiationDeclaration: 370351280Sdim case TSK_ExplicitInstantiationDefinition: 371351280Sdim if (!DumpExplicitInst) 372351280Sdim break; 373351280Sdim LLVM_FALLTHROUGH; 374351280Sdim case TSK_Undeclared: 375351280Sdim case TSK_ImplicitInstantiation: 376351280Sdim if (DumpRefOnly) 377351280Sdim NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(Redecl); }); 378351280Sdim else 379351280Sdim Visit(Redecl); 380351280Sdim DumpedAny = true; 381351280Sdim break; 382351280Sdim case TSK_ExplicitSpecialization: 383351280Sdim break; 384351280Sdim } 385351280Sdim } 386351280Sdim 387351280Sdim // Ensure we dump at least one decl for each specialization. 388351280Sdim if (!DumpedAny) 389351280Sdim NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(SD); }); 390351280Sdim } 391351280Sdim 392351280Sdim template <typename TemplateDecl> 393351280Sdim void writeTemplateDecl(const TemplateDecl *TD, bool DumpExplicitInst) { 394351280Sdim // FIXME: it would be nice to dump template parameters and specializations 395351280Sdim // to their own named arrays rather than shoving them into the "inner" 396351280Sdim // array. However, template declarations are currently being handled at the 397351280Sdim // wrong "level" of the traversal hierarchy and so it is difficult to 398351280Sdim // achieve without losing information elsewhere. 399351280Sdim 400351280Sdim dumpTemplateParameters(TD->getTemplateParameters()); 401351280Sdim 402351280Sdim Visit(TD->getTemplatedDecl()); 403351280Sdim 404351280Sdim for (const auto *Child : TD->specializations()) 405351280Sdim writeTemplateDeclSpecialization(Child, DumpExplicitInst, 406351280Sdim !TD->isCanonicalDecl()); 407351280Sdim } 408351280Sdim 409351280Sdimpublic: 410351280Sdim JSONDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx, 411351280Sdim const PrintingPolicy &PrintPolicy, 412351280Sdim const comments::CommandTraits *Traits) 413351280Sdim : NodeDumper(OS, SrcMgr, Ctx, PrintPolicy, Traits) {} 414351280Sdim 415351280Sdim JSONNodeDumper &doGetNodeDelegate() { return NodeDumper; } 416351280Sdim 417351280Sdim void VisitFunctionTemplateDecl(const FunctionTemplateDecl *FTD) { 418351280Sdim writeTemplateDecl(FTD, true); 419351280Sdim } 420351280Sdim void VisitClassTemplateDecl(const ClassTemplateDecl *CTD) { 421351280Sdim writeTemplateDecl(CTD, false); 422351280Sdim } 423351280Sdim void VisitVarTemplateDecl(const VarTemplateDecl *VTD) { 424351280Sdim writeTemplateDecl(VTD, false); 425351280Sdim } 426351280Sdim}; 427351280Sdim 428351280Sdim} // namespace clang 429351280Sdim 430351280Sdim#endif // LLVM_CLANG_AST_JSONNODEDUMPER_H 431