1 //===--- JSONNodeDumper.h - Printing of AST nodes to JSON -----------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements AST dumping of components of individual AST nodes to
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_AST_JSONNODEDUMPER_H
16 #define LLVM_CLANG_AST_JSONNODEDUMPER_H
18 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/ASTDumperUtils.h"
20 #include "clang/AST/ASTNodeTraverser.h"
21 #include "clang/AST/AttrVisitor.h"
22 #include "clang/AST/CommentCommandTraits.h"
23 #include "clang/AST/CommentVisitor.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"
34 bool FirstChild = true;
36 llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending;
39 llvm::json::OStream JOS;
42 /// Add a child of the current node. Calls DoAddChild without arguments
43 template <typename Fn> void AddChild(Fn DoAddChild) {
44 return AddChild("", DoAddChild);
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
58 while (!Pending.empty()) {
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) {
74 JOS.attributeBegin(LabelStr);
79 unsigned Depth = Pending.size();
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()) {
88 this->Pending.pop_back();
100 Pending.push_back(std::move(DumpWithIndent));
102 Pending.back()(false);
103 Pending.back() = std::move(DumpWithIndent);
108 NodeStreamer(raw_ostream &OS) : JOS(OS, 2) {}
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.
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;
127 const SourceManager &SM;
129 ASTNameGenerator ASTNameGen;
130 PrintingPolicy PrintPolicy;
131 const comments::CommandTraits *Traits;
132 StringRef LastLocFilename, LastLocPresumedFilename;
133 unsigned LastLocLine, LastLocPresumedLine;
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>;
144 void attributeOnlyIfTrue(StringRef Key, bool Value) {
146 JOS.attribute(Key, Value);
149 void writeIncludeStack(PresumedLoc Loc, bool JustFirst = false);
151 // Writes the attributes of a SourceLocation object without.
152 void writeBareSourceLocation(SourceLocation Loc, bool IsSpelling);
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 void writeBareDeclRef(const Decl *D);
164 llvm::json::Object createCXXRecordDefinitionData(const CXXRecordDecl *RD);
165 llvm::json::Object createCXXBaseSpecifier(const CXXBaseSpecifier &BS);
166 std::string createAccessSpecifier(AccessSpecifier AS);
167 llvm::json::Array createCastPath(const CastExpr *C);
169 void writePreviousDeclImpl(...) {}
171 template <typename T> void writePreviousDeclImpl(const Mergeable<T> *D) {
172 const T *First = D->getFirstDecl();
174 JOS.attribute("firstRedecl", createPointerRepresentation(First));
177 template <typename T> void writePreviousDeclImpl(const Redeclarable<T> *D) {
178 const T *Prev = D->getPreviousDecl();
180 JOS.attribute("previousDecl", createPointerRepresentation(Prev));
182 void addPreviousDeclaration(const Decl *D);
184 StringRef getCommentCommandName(unsigned CommandID) const;
187 JSONNodeDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx,
188 const PrintingPolicy &PrintPolicy,
189 const comments::CommandTraits *Traits)
190 : NodeStreamer(OS), SM(SrcMgr), Ctx(Ctx), ASTNameGen(Ctx),
191 PrintPolicy(PrintPolicy), Traits(Traits), LastLocLine(0),
192 LastLocPresumedLine(0) {}
194 void Visit(const Attr *A);
195 void Visit(const Stmt *Node);
196 void Visit(const Type *T);
197 void Visit(QualType T);
198 void Visit(const Decl *D);
200 void Visit(const comments::Comment *C, const comments::FullComment *FC);
201 void Visit(const TemplateArgument &TA, SourceRange R = {},
202 const Decl *From = nullptr, StringRef Label = {});
203 void Visit(const CXXCtorInitializer *Init);
204 void Visit(const OMPClause *C);
205 void Visit(const BlockDecl::Capture &C);
206 void Visit(const GenericSelectionExpr::ConstAssociation &A);
207 void Visit(const APValue &Value, QualType Ty);
209 void VisitTypedefType(const TypedefType *TT);
210 void VisitFunctionType(const FunctionType *T);
211 void VisitFunctionProtoType(const FunctionProtoType *T);
212 void VisitRValueReferenceType(const ReferenceType *RT);
213 void VisitArrayType(const ArrayType *AT);
214 void VisitConstantArrayType(const ConstantArrayType *CAT);
215 void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *VT);
216 void VisitVectorType(const VectorType *VT);
217 void VisitUnresolvedUsingType(const UnresolvedUsingType *UUT);
218 void VisitUnaryTransformType(const UnaryTransformType *UTT);
219 void VisitTagType(const TagType *TT);
220 void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT);
221 void VisitAutoType(const AutoType *AT);
222 void VisitTemplateSpecializationType(const TemplateSpecializationType *TST);
223 void VisitInjectedClassNameType(const InjectedClassNameType *ICNT);
224 void VisitObjCInterfaceType(const ObjCInterfaceType *OIT);
225 void VisitPackExpansionType(const PackExpansionType *PET);
226 void VisitElaboratedType(const ElaboratedType *ET);
227 void VisitMacroQualifiedType(const MacroQualifiedType *MQT);
228 void VisitMemberPointerType(const MemberPointerType *MPT);
230 void VisitNamedDecl(const NamedDecl *ND);
231 void VisitTypedefDecl(const TypedefDecl *TD);
232 void VisitTypeAliasDecl(const TypeAliasDecl *TAD);
233 void VisitNamespaceDecl(const NamespaceDecl *ND);
234 void VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD);
235 void VisitNamespaceAliasDecl(const NamespaceAliasDecl *NAD);
236 void VisitUsingDecl(const UsingDecl *UD);
237 void VisitUsingShadowDecl(const UsingShadowDecl *USD);
238 void VisitVarDecl(const VarDecl *VD);
239 void VisitFieldDecl(const FieldDecl *FD);
240 void VisitFunctionDecl(const FunctionDecl *FD);
241 void VisitEnumDecl(const EnumDecl *ED);
242 void VisitEnumConstantDecl(const EnumConstantDecl *ECD);
243 void VisitRecordDecl(const RecordDecl *RD);
244 void VisitCXXRecordDecl(const CXXRecordDecl *RD);
245 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
246 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
247 void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
248 void VisitLinkageSpecDecl(const LinkageSpecDecl *LSD);
249 void VisitAccessSpecDecl(const AccessSpecDecl *ASD);
250 void VisitFriendDecl(const FriendDecl *FD);
252 void VisitObjCIvarDecl(const ObjCIvarDecl *D);
253 void VisitObjCMethodDecl(const ObjCMethodDecl *D);
254 void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D);
255 void VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
256 void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D);
257 void VisitObjCProtocolDecl(const ObjCProtocolDecl *D);
258 void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D);
259 void VisitObjCImplementationDecl(const ObjCImplementationDecl *D);
260 void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D);
261 void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
262 void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
263 void VisitBlockDecl(const BlockDecl *D);
265 void VisitDeclRefExpr(const DeclRefExpr *DRE);
266 void VisitPredefinedExpr(const PredefinedExpr *PE);
267 void VisitUnaryOperator(const UnaryOperator *UO);
268 void VisitBinaryOperator(const BinaryOperator *BO);
269 void VisitCompoundAssignOperator(const CompoundAssignOperator *CAO);
270 void VisitMemberExpr(const MemberExpr *ME);
271 void VisitCXXNewExpr(const CXXNewExpr *NE);
272 void VisitCXXDeleteExpr(const CXXDeleteExpr *DE);
273 void VisitCXXThisExpr(const CXXThisExpr *TE);
274 void VisitCastExpr(const CastExpr *CE);
275 void VisitImplicitCastExpr(const ImplicitCastExpr *ICE);
276 void VisitCallExpr(const CallExpr *CE);
277 void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *TTE);
278 void VisitSizeOfPackExpr(const SizeOfPackExpr *SOPE);
279 void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *ULE);
280 void VisitAddrLabelExpr(const AddrLabelExpr *ALE);
281 void VisitCXXTypeidExpr(const CXXTypeidExpr *CTE);
282 void VisitConstantExpr(const ConstantExpr *CE);
283 void VisitInitListExpr(const InitListExpr *ILE);
284 void VisitGenericSelectionExpr(const GenericSelectionExpr *GSE);
285 void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *UCE);
286 void VisitCXXConstructExpr(const CXXConstructExpr *CE);
287 void VisitExprWithCleanups(const ExprWithCleanups *EWC);
288 void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE);
289 void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE);
290 void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *ME);
292 void VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE);
293 void VisitObjCMessageExpr(const ObjCMessageExpr *OME);
294 void VisitObjCBoxedExpr(const ObjCBoxedExpr *OBE);
295 void VisitObjCSelectorExpr(const ObjCSelectorExpr *OSE);
296 void VisitObjCProtocolExpr(const ObjCProtocolExpr *OPE);
297 void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *OPRE);
298 void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *OSRE);
299 void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *OIRE);
300 void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *OBLE);
302 void VisitIntegerLiteral(const IntegerLiteral *IL);
303 void VisitCharacterLiteral(const CharacterLiteral *CL);
304 void VisitFixedPointLiteral(const FixedPointLiteral *FPL);
305 void VisitFloatingLiteral(const FloatingLiteral *FL);
306 void VisitStringLiteral(const StringLiteral *SL);
307 void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *BLE);
309 void VisitIfStmt(const IfStmt *IS);
310 void VisitSwitchStmt(const SwitchStmt *SS);
311 void VisitCaseStmt(const CaseStmt *CS);
312 void VisitLabelStmt(const LabelStmt *LS);
313 void VisitGotoStmt(const GotoStmt *GS);
314 void VisitWhileStmt(const WhileStmt *WS);
315 void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *OACS);
317 void VisitNullTemplateArgument(const TemplateArgument &TA);
318 void VisitTypeTemplateArgument(const TemplateArgument &TA);
319 void VisitDeclarationTemplateArgument(const TemplateArgument &TA);
320 void VisitNullPtrTemplateArgument(const TemplateArgument &TA);
321 void VisitIntegralTemplateArgument(const TemplateArgument &TA);
322 void VisitTemplateTemplateArgument(const TemplateArgument &TA);
323 void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA);
324 void VisitExpressionTemplateArgument(const TemplateArgument &TA);
325 void VisitPackTemplateArgument(const TemplateArgument &TA);
327 void visitTextComment(const comments::TextComment *C,
328 const comments::FullComment *);
329 void visitInlineCommandComment(const comments::InlineCommandComment *C,
330 const comments::FullComment *);
331 void visitHTMLStartTagComment(const comments::HTMLStartTagComment *C,
332 const comments::FullComment *);
333 void visitHTMLEndTagComment(const comments::HTMLEndTagComment *C,
334 const comments::FullComment *);
335 void visitBlockCommandComment(const comments::BlockCommandComment *C,
336 const comments::FullComment *);
337 void visitParamCommandComment(const comments::ParamCommandComment *C,
338 const comments::FullComment *FC);
339 void visitTParamCommandComment(const comments::TParamCommandComment *C,
340 const comments::FullComment *FC);
341 void visitVerbatimBlockComment(const comments::VerbatimBlockComment *C,
342 const comments::FullComment *);
344 visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment *C,
345 const comments::FullComment *);
346 void visitVerbatimLineComment(const comments::VerbatimLineComment *C,
347 const comments::FullComment *);
350 class JSONDumper : public ASTNodeTraverser<JSONDumper, JSONNodeDumper> {
351 JSONNodeDumper NodeDumper;
353 template <typename SpecializationDecl>
354 void writeTemplateDeclSpecialization(const SpecializationDecl *SD,
355 bool DumpExplicitInst,
357 bool DumpedAny = false;
358 for (const auto *RedeclWithBadType : SD->redecls()) {
359 // FIXME: The redecls() range sometimes has elements of a less-specific
360 // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
361 // us TagDecls, and should give CXXRecordDecls).
362 const auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
364 // Found the injected-class-name for a class template. This will be
365 // dumped as part of its surrounding class so we don't need to dump it
367 assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
368 "expected an injected-class-name");
372 switch (Redecl->getTemplateSpecializationKind()) {
373 case TSK_ExplicitInstantiationDeclaration:
374 case TSK_ExplicitInstantiationDefinition:
375 if (!DumpExplicitInst)
379 case TSK_ImplicitInstantiation:
381 NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(Redecl); });
386 case TSK_ExplicitSpecialization:
391 // Ensure we dump at least one decl for each specialization.
393 NodeDumper.AddChild([=] { NodeDumper.writeBareDeclRef(SD); });
396 template <typename TemplateDecl>
397 void writeTemplateDecl(const TemplateDecl *TD, bool DumpExplicitInst) {
398 // FIXME: it would be nice to dump template parameters and specializations
399 // to their own named arrays rather than shoving them into the "inner"
400 // array. However, template declarations are currently being handled at the
401 // wrong "level" of the traversal hierarchy and so it is difficult to
402 // achieve without losing information elsewhere.
404 dumpTemplateParameters(TD->getTemplateParameters());
406 Visit(TD->getTemplatedDecl());
408 for (const auto *Child : TD->specializations())
409 writeTemplateDeclSpecialization(Child, DumpExplicitInst,
410 !TD->isCanonicalDecl());
414 JSONDumper(raw_ostream &OS, const SourceManager &SrcMgr, ASTContext &Ctx,
415 const PrintingPolicy &PrintPolicy,
416 const comments::CommandTraits *Traits)
417 : NodeDumper(OS, SrcMgr, Ctx, PrintPolicy, Traits) {}
419 JSONNodeDumper &doGetNodeDelegate() { return NodeDumper; }
421 void VisitFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
422 writeTemplateDecl(FTD, true);
424 void VisitClassTemplateDecl(const ClassTemplateDecl *CTD) {
425 writeTemplateDecl(CTD, false);
427 void VisitVarTemplateDecl(const VarTemplateDecl *VTD) {
428 writeTemplateDecl(VTD, false);
434 #endif // LLVM_CLANG_AST_JSONNODEDUMPER_H