Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===--- JSONNodeDumper.h - Printing of AST nodes to JSON -----------------===// |
2 | // |
||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
4 | // See https://llvm.org/LICENSE.txt for license information. |
||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
6 | // |
||
7 | //===----------------------------------------------------------------------===// |
||
8 | // |
||
9 | // This file implements AST dumping of components of individual AST nodes to |
||
10 | // a JSON. |
||
11 | // |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_CLANG_AST_JSONNODEDUMPER_H |
||
15 | #define LLVM_CLANG_AST_JSONNODEDUMPER_H |
||
16 | |||
17 | #include "clang/AST/ASTContext.h" |
||
18 | #include "clang/AST/ASTDumperUtils.h" |
||
19 | #include "clang/AST/ASTNodeTraverser.h" |
||
20 | #include "clang/AST/AttrVisitor.h" |
||
21 | #include "clang/AST/CommentCommandTraits.h" |
||
22 | #include "clang/AST/CommentVisitor.h" |
||
23 | #include "clang/AST/ExprConcepts.h" |
||
24 | #include "clang/AST/ExprCXX.h" |
||
25 | #include "clang/AST/Mangle.h" |
||
26 | #include "clang/AST/Type.h" |
||
27 | #include "llvm/Support/JSON.h" |
||
28 | |||
29 | namespace clang { |
||
30 | |||
31 | class APValue; |
||
32 | |||
33 | class NodeStreamer { |
||
34 | bool FirstChild = true; |
||
35 | bool TopLevel = true; |
||
36 | llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending; |
||
37 | |||
38 | protected: |
||
39 | llvm::json::OStream JOS; |
||
40 | |||
41 | public: |
||
42 | /// Add a child of the current node. Calls DoAddChild without arguments |
||
43 | template <typename Fn> void AddChild(Fn DoAddChild) { |
||
44 | return AddChild("", DoAddChild); |
||
45 | } |
||
46 | |||
47 | /// Add a child of the current node with an optional label. |
||
48 | /// Calls DoAddChild without arguments. |
||
49 | template <typename Fn> void AddChild(StringRef Label, Fn DoAddChild) { |
||
50 | // If we're at the top level, there's nothing interesting to do; just |
||
51 | // run the dumper. |
||
52 | if (TopLevel) { |
||
53 | TopLevel = false; |
||
54 | JOS.objectBegin(); |
||
55 | |||
56 | DoAddChild(); |
||
57 | |||
58 | while (!Pending.empty()) { |
||
59 | Pending.back()(true); |
||
60 | Pending.pop_back(); |
||
61 | } |
||
62 | |||
63 | JOS.objectEnd(); |
||
64 | TopLevel = true; |
||
65 | return; |
||
66 | } |
||
67 | |||
68 | // We need to capture an owning-string in the lambda because the lambda |
||
69 | // is invoked in a deferred manner. |
||
70 | std::string LabelStr(!Label.empty() ? Label : "inner"); |
||
71 | bool WasFirstChild = FirstChild; |
||
72 | auto DumpWithIndent = [=](bool IsLastChild) { |
||
73 | if (WasFirstChild) { |
||
74 | JOS.attributeBegin(LabelStr); |
||
75 | JOS.arrayBegin(); |
||
76 | } |
||
77 | |||
78 | FirstChild = true; |
||
79 | unsigned Depth = Pending.size(); |
||
80 | JOS.objectBegin(); |
||
81 | |||
82 | DoAddChild(); |
||
83 | |||
84 | // If any children are left, they're the last at their nesting level. |
||
85 | // Dump those ones out now. |
||
86 | while (Depth < Pending.size()) { |
||
87 | Pending.back()(true); |
||
88 | this->Pending.pop_back(); |
||
89 | } |
||
90 | |||
91 | JOS.objectEnd(); |
||
92 | |||
93 | if (IsLastChild) { |
||
94 | JOS.arrayEnd(); |
||
95 | JOS.attributeEnd(); |
||
96 | } |
||
97 | }; |
||
98 | |||
99 | if (FirstChild) { |
||
100 | Pending.push_back(std::move(DumpWithIndent)); |
||
101 | } else { |
||
102 | Pending.back()(false); |
||
103 | Pending.back() = std::move(DumpWithIndent); |
||
104 | } |
||
105 | FirstChild = false; |
||
106 | } |
||
107 | |||
108 | NodeStreamer(raw_ostream &OS) : JOS(OS, 2) {} |
||
109 | }; |
||
110 | |||
111 | // Dumps AST nodes in JSON format. There is no implied stability for the |
||
112 | // content or format of the dump between major releases of Clang, other than it |
||
113 | // being valid JSON output. Further, there is no requirement that the |
||
114 | // information dumped is a complete representation of the AST, only that the |
||
115 | // information presented is correct. |
||
116 | class JSONNodeDumper |
||
117 | : public ConstAttrVisitor<JSONNodeDumper>, |
||
118 | public comments::ConstCommentVisitor<JSONNodeDumper, void, |
||
119 | const comments::FullComment *>, |
||
120 | public ConstTemplateArgumentVisitor<JSONNodeDumper>, |
||
121 | public ConstStmtVisitor<JSONNodeDumper>, |
||
122 | public TypeVisitor<JSONNodeDumper>, |
||
123 | public ConstDeclVisitor<JSONNodeDumper>, |
||
124 | public NodeStreamer { |
||
125 | friend class JSONDumper; |
||
126 | |||
127 | const SourceManager &SM; |
||
128 | ASTContext& Ctx; |
||
129 | ASTNameGenerator ASTNameGen; |
||
130 | PrintingPolicy PrintPolicy; |
||
131 | const comments::CommandTraits *Traits; |
||
132 | StringRef LastLocFilename, LastLocPresumedFilename; |
||
133 | unsigned LastLocLine, LastLocPresumedLine; |
||
134 | |||
135 | using InnerAttrVisitor = ConstAttrVisitor<JSONNodeDumper>; |
||
136 | using InnerCommentVisitor = |
||
137 | comments::ConstCommentVisitor<JSONNodeDumper, void, |
||
138 | const comments::FullComment *>; |
||
139 | using InnerTemplateArgVisitor = ConstTemplateArgumentVisitor<JSONNodeDumper>; |
||
140 | using InnerStmtVisitor = ConstStmtVisitor<JSONNodeDumper>; |
||
141 | using InnerTypeVisitor = TypeVisitor<JSONNodeDumper>; |
||
142 | using InnerDeclVisitor = ConstDeclVisitor<JSONNodeDumper>; |
||
143 | |||
144 | void attributeOnlyIfTrue(StringRef Key, bool Value) { |
||
145 | if (Value) |
||
146 | JOS.attribute(Key, Value); |
||
147 | } |
||
148 | |||
149 | void writeIncludeStack(PresumedLoc Loc, bool JustFirst = false); |
||
150 | |||
151 | // Writes the attributes of a SourceLocation object without. |
||
152 | void writeBareSourceLocation(SourceLocation Loc, bool IsSpelling); |
||
153 | |||
154 | // Writes the attributes of a SourceLocation to JSON based on its presumed |
||
155 | // spelling location. If the given location represents a macro invocation, |
||
156 | // this outputs two sub-objects: one for the spelling and one for the |
||
157 | // expansion location. |
||
158 | void writeSourceLocation(SourceLocation Loc); |
||
159 | void writeSourceRange(SourceRange R); |
||
160 | std::string createPointerRepresentation(const void *Ptr); |
||
161 | llvm::json::Object createQualType(QualType QT, bool Desugar = true); |
||
162 | llvm::json::Object createBareDeclRef(const Decl *D); |
||
163 | llvm::json::Object createFPOptions(FPOptionsOverride FPO); |
||
164 | void writeBareDeclRef(const Decl *D); |
||
165 | llvm::json::Object createCXXRecordDefinitionData(const CXXRecordDecl *RD); |
||
166 | llvm::json::Object createCXXBaseSpecifier(const CXXBaseSpecifier &BS); |
||
167 | std::string createAccessSpecifier(AccessSpecifier AS); |
||
168 | llvm::json::Array createCastPath(const CastExpr *C); |
||
169 | |||
170 | void writePreviousDeclImpl(...) {} |
||
171 | |||
172 | template <typename T> void writePreviousDeclImpl(const Mergeable<T> *D) { |
||
173 | const T *First = D->getFirstDecl(); |
||
174 | if (First != D) |
||
175 | JOS.attribute("firstRedecl", createPointerRepresentation(First)); |
||
176 | } |
||
177 | |||
178 | template <typename T> void writePreviousDeclImpl(const Redeclarable<T> *D) { |
||
179 | const T *Prev = D->getPreviousDecl(); |
||
180 | if (Prev) |
||
181 | JOS.attribute("previousDecl", createPointerRepresentation(Prev)); |
||
182 | } |
||
183 | void addPreviousDeclaration(const Decl *D); |
||
184 | |||
185 | StringRef getCommentCommandName(unsigned CommandID) const; |
||
186 | |||
187 | public: |
||
188 | JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx, |
||
189 | const PrintingPolicy &PrintPolicy, |
||
190 | const comments::CommandTraits *Traits) |
||
191 | : NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), ASTNameGen(Ctx), |
||
192 | PrintPolicy(PrintPolicy), Traits(Traits), LastLocLine(0), |
||
193 | LastLocPresumedLine(0) {} |
||
194 | |||
195 | void Visit(const Attr *A); |
||
196 | void Visit(const Stmt *Node); |
||
197 | void Visit(const Type *T); |
||
198 | void Visit(QualType T); |
||
199 | void Visit(const Decl *D); |
||
200 | |||
201 | void Visit(const comments::Comment *C, const comments::FullComment *FC); |
||
202 | void Visit(const TemplateArgument &TA, SourceRange R = {}, |
||
203 | const Decl *From = nullptr, StringRef Label = {}); |
||
204 | void Visit(const CXXCtorInitializer *Init); |
||
205 | void Visit(const OMPClause *C); |
||
206 | void Visit(const BlockDecl::Capture &C); |
||
207 | void Visit(const GenericSelectionExpr::ConstAssociation &A); |
||
208 | void Visit(const concepts::Requirement *R); |
||
209 | void Visit(const APValue &Value, QualType Ty); |
||
210 | |||
211 | void VisitTypedefType(const TypedefType *TT); |
||
212 | void VisitUsingType(const UsingType *TT); |
||
213 | void VisitFunctionType(const FunctionType *T); |
||
214 | void VisitFunctionProtoType(const FunctionProtoType *T); |
||
215 | void VisitRValueReferenceType(const ReferenceType *RT); |
||
216 | void VisitArrayType(const ArrayType *AT); |
||
217 | void VisitConstantArrayType(const ConstantArrayType *CAT); |
||
218 | void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *VT); |
||
219 | void VisitVectorType(const VectorType *VT); |
||
220 | void VisitUnresolvedUsingType(const UnresolvedUsingType *UUT); |
||
221 | void VisitUnaryTransformType(const UnaryTransformType *UTT); |
||
222 | void VisitTagType(const TagType *TT); |
||
223 | void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT); |
||
224 | void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT); |
||
225 | void |
||
226 | VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T); |
||
227 | void VisitAutoType(const AutoType *AT); |
||
228 | void VisitTemplateSpecializationType(const TemplateSpecializationType *TST); |
||
229 | void VisitInjectedClassNameType(const InjectedClassNameType *ICNT); |
||
230 | void VisitObjCInterfaceType(const ObjCInterfaceType *OIT); |
||
231 | void VisitPackExpansionType(const PackExpansionType *PET); |
||
232 | void VisitElaboratedType(const ElaboratedType *ET); |
||
233 | void VisitMacroQualifiedType(const MacroQualifiedType *MQT); |
||
234 | void VisitMemberPointerType(const MemberPointerType *MPT); |
||
235 | |||
236 | void VisitNamedDecl(const NamedDecl *ND); |
||
237 | void VisitTypedefDecl(const TypedefDecl *TD); |
||
238 | void VisitTypeAliasDecl(const TypeAliasDecl *TAD); |
||
239 | void VisitNamespaceDecl(const NamespaceDecl *ND); |
||
240 | void VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD); |
||
241 | void VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD); |
||
242 | void VisitUsingDecl(const UsingDecl *UD); |
||
243 | void VisitUsingEnumDecl(const UsingEnumDecl *UED); |
||
244 | void VisitUsingShadowDecl(const UsingShadowDecl *USD); |
||
245 | void VisitVarDecl(const VarDecl *VD); |
||
246 | void VisitFieldDecl(const FieldDecl *FD); |
||
247 | void VisitFunctionDecl(const FunctionDecl *FD); |
||
248 | void VisitEnumDecl(const EnumDecl *ED); |
||
249 | void VisitEnumConstantDecl(const EnumConstantDecl *ECD); |
||
250 | void VisitRecordDecl(const RecordDecl *RD); |
||
251 | void VisitCXXRecordDecl(const CXXRecordDecl *RD); |
||
252 | void VisitHLSLBufferDecl(const HLSLBufferDecl *D); |
||
253 | void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); |
||
254 | void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); |
||
255 | void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); |
||
256 | void VisitLinkageSpecDecl(const LinkageSpecDecl *LSD); |
||
257 | void VisitAccessSpecDecl(const AccessSpecDecl *ASD); |
||
258 | void VisitFriendDecl(const FriendDecl *FD); |
||
259 | |||
260 | void VisitObjCIvarDecl(const ObjCIvarDecl *D); |
||
261 | void VisitObjCMethodDecl(const ObjCMethodDecl *D); |
||
262 | void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D); |
||
263 | void VisitObjCCategoryDecl(const ObjCCategoryDecl *D); |
||
264 | void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D); |
||
265 | void VisitObjCProtocolDecl(const ObjCProtocolDecl *D); |
||
266 | void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D); |
||
267 | void VisitObjCImplementationDecl(const ObjCImplementationDecl *D); |
||
268 | void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D); |
||
269 | void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); |
||
270 | void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); |
||
271 | void VisitBlockDecl(const BlockDecl *D); |
||
272 | |||
273 | void VisitDeclRefExpr(const DeclRefExpr *DRE); |
||
274 | void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E); |
||
275 | void VisitPredefinedExpr(const PredefinedExpr *PE); |
||
276 | void VisitUnaryOperator(const UnaryOperator *UO); |
||
277 | void VisitBinaryOperator(const BinaryOperator *BO); |
||
278 | void VisitCompoundAssignOperator(const CompoundAssignOperator *CAO); |
||
279 | void VisitMemberExpr(const MemberExpr *ME); |
||
280 | void VisitCXXNewExpr(const CXXNewExpr *NE); |
||
281 | void VisitCXXDeleteExpr(const CXXDeleteExpr *DE); |
||
282 | void VisitCXXThisExpr(const CXXThisExpr *TE); |
||
283 | void VisitCastExpr(const CastExpr *CE); |
||
284 | void VisitImplicitCastExpr(const ImplicitCastExpr *ICE); |
||
285 | void VisitCallExpr(const CallExpr *CE); |
||
286 | void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *TTE); |
||
287 | void VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE); |
||
288 | void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *ULE); |
||
289 | void VisitAddrLabelExpr(const AddrLabelExpr *ALE); |
||
290 | void VisitCXXTypeidExpr(const CXXTypeidExpr *CTE); |
||
291 | void VisitConstantExpr(const ConstantExpr *CE); |
||
292 | void VisitInitListExpr(const InitListExpr *ILE); |
||
293 | void VisitGenericSelectionExpr(const GenericSelectionExpr *GSE); |
||
294 | void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *UCE); |
||
295 | void VisitCXXConstructExpr(const CXXConstructExpr *CE); |
||
296 | void VisitExprWithCleanups(const ExprWithCleanups *EWC); |
||
297 | void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE); |
||
298 | void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE); |
||
299 | void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *ME); |
||
300 | void VisitRequiresExpr(const RequiresExpr *RE); |
||
301 | |||
302 | void VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE); |
||
303 | void VisitObjCMessageExpr(const ObjCMessageExpr *OME); |
||
304 | void VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE); |
||
305 | void VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE); |
||
306 | void VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE); |
||
307 | void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE); |
||
308 | void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *OSRE); |
||
309 | void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE); |
||
310 | void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE); |
||
311 | |||
312 | void VisitIntegerLiteral(const IntegerLiteral *IL); |
||
313 | void VisitCharacterLiteral(const CharacterLiteral *CL); |
||
314 | void VisitFixedPointLiteral(const FixedPointLiteral *FPL); |
||
315 | void VisitFloatingLiteral(const FloatingLiteral *FL); |
||
316 | void VisitStringLiteral(const StringLiteral *SL); |
||
317 | void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE); |
||
318 | |||
319 | void VisitIfStmt(const IfStmt *IS); |
||
320 | void VisitSwitchStmt(const SwitchStmt *SS); |
||
321 | void VisitCaseStmt(const CaseStmt *CS); |
||
322 | void VisitLabelStmt(const LabelStmt *LS); |
||
323 | void VisitGotoStmt(const GotoStmt *GS); |
||
324 | void VisitWhileStmt(const WhileStmt *WS); |
||
325 | void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *OACS); |
||
326 | void VisitCompoundStmt(const CompoundStmt *IS); |
||
327 | |||
328 | void VisitNullTemplateArgument(const TemplateArgument &TA); |
||
329 | void VisitTypeTemplateArgument(const TemplateArgument &TA); |
||
330 | void VisitDeclarationTemplateArgument(const TemplateArgument &TA); |
||
331 | void VisitNullPtrTemplateArgument(const TemplateArgument &TA); |
||
332 | void VisitIntegralTemplateArgument(const TemplateArgument &TA); |
||
333 | void VisitTemplateTemplateArgument(const TemplateArgument &TA); |
||
334 | void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA); |
||
335 | void VisitExpressionTemplateArgument(const TemplateArgument &TA); |
||
336 | void VisitPackTemplateArgument(const TemplateArgument &TA); |
||
337 | |||
338 | void visitTextComment(const comments::TextComment *C, |
||
339 | const comments::FullComment *); |
||
340 | void visitInlineCommandComment(const comments::InlineCommandComment *C, |
||
341 | const comments::FullComment *); |
||
342 | void visitHTMLStartTagComment(const comments::HTMLStartTagComment *C, |
||
343 | const comments::FullComment *); |
||
344 | void visitHTMLEndTagComment(const comments::HTMLEndTagComment *C, |
||
345 | const comments::FullComment *); |
||
346 | void visitBlockCommandComment(const comments::BlockCommandComment *C, |
||
347 | const comments::FullComment *); |
||
348 | void visitParamCommandComment(const comments::ParamCommandComment *C, |
||
349 | const comments::FullComment *FC); |
||
350 | void visitTParamCommandComment(const comments::TParamCommandComment *C, |
||
351 | const comments::FullComment *FC); |
||
352 | void visitVerbatimBlockComment(const comments::VerbatimBlockComment *C, |
||
353 | const comments::FullComment *); |
||
354 | void |
||
355 | visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment *C, |
||
356 | const comments::FullComment *); |
||
357 | void visitVerbatimLineComment(const comments::VerbatimLineComment *C, |
||
358 | const comments::FullComment *); |
||
359 | }; |
||
360 | |||
361 | class JSONDumper : public ASTNodeTraverser<JSONDumper, JSONNodeDumper> { |
||
362 | JSONNodeDumper NodeDumper; |
||
363 | |||
364 | template <typename SpecializationDecl> |
||
365 | void writeTemplateDeclSpecialization(const SpecializationDecl *SD, |
||
366 | bool DumpExplicitInst, |
||
367 | bool DumpRefOnly) { |
||
368 | bool DumpedAny = false; |
||
369 | for (const auto *RedeclWithBadType : SD->redecls()) { |
||
370 | // FIXME: The redecls() range sometimes has elements of a less-specific |
||
371 | // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives |
||
372 | // us TagDecls, and should give CXXRecordDecls). |
||
373 | const auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType); |
||
374 | if (!Redecl) { |
||
375 | // Found the injected-class-name for a class template. This will be |
||
376 | // dumped as part of its surrounding class so we don't need to dump it |
||
377 | // here. |
||
378 | assert(isa<CXXRecordDecl>(RedeclWithBadType) && |
||
379 | "expected an injected-class-name"); |
||
380 | continue; |
||
381 | } |
||
382 | |||
383 | switch (Redecl->getTemplateSpecializationKind()) { |
||
384 | case TSK_ExplicitInstantiationDeclaration: |
||
385 | case TSK_ExplicitInstantiationDefinition: |
||
386 | if (!DumpExplicitInst) |
||
387 | break; |
||
388 | [[fallthrough]]; |
||
389 | case TSK_Undeclared: |
||
390 | case TSK_ImplicitInstantiation: |
||
391 | if (DumpRefOnly) |
||
392 | NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(Redecl); }); |
||
393 | else |
||
394 | Visit(Redecl); |
||
395 | DumpedAny = true; |
||
396 | break; |
||
397 | case TSK_ExplicitSpecialization: |
||
398 | break; |
||
399 | } |
||
400 | } |
||
401 | |||
402 | // Ensure we dump at least one decl for each specialization. |
||
403 | if (!DumpedAny) |
||
404 | NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(SD); }); |
||
405 | } |
||
406 | |||
407 | template <typename TemplateDecl> |
||
408 | void writeTemplateDecl(const TemplateDecl *TD, bool DumpExplicitInst) { |
||
409 | // FIXME: it would be nice to dump template parameters and specializations |
||
410 | // to their own named arrays rather than shoving them into the "inner" |
||
411 | // array. However, template declarations are currently being handled at the |
||
412 | // wrong "level" of the traversal hierarchy and so it is difficult to |
||
413 | // achieve without losing information elsewhere. |
||
414 | |||
415 | dumpTemplateParameters(TD->getTemplateParameters()); |
||
416 | |||
417 | Visit(TD->getTemplatedDecl()); |
||
418 | |||
419 | for (const auto *Child : TD->specializations()) |
||
420 | writeTemplateDeclSpecialization(Child, DumpExplicitInst, |
||
421 | !TD->isCanonicalDecl()); |
||
422 | } |
||
423 | |||
424 | public: |
||
425 | JSONDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx, |
||
426 | const PrintingPolicy &PrintPolicy, |
||
427 | const comments::CommandTraits *Traits) |
||
428 | : NodeDumper(OS, SrcMgr, Ctx, PrintPolicy, Traits) {} |
||
429 | |||
430 | JSONNodeDumper &doGetNodeDelegate() { return NodeDumper; } |
||
431 | |||
432 | void VisitFunctionTemplateDecl(const FunctionTemplateDecl *FTD) { |
||
433 | writeTemplateDecl(FTD, true); |
||
434 | } |
||
435 | void VisitClassTemplateDecl(const ClassTemplateDecl *CTD) { |
||
436 | writeTemplateDecl(CTD, false); |
||
437 | } |
||
438 | void VisitVarTemplateDecl(const VarTemplateDecl *VTD) { |
||
439 | writeTemplateDecl(VTD, false); |
||
440 | } |
||
441 | }; |
||
442 | |||
443 | } // namespace clang |
||
444 | |||
445 | #endif // LLVM_CLANG_AST_JSONNODEDUMPER_H |