1//===--- TextNodeDumper.h - Printing of AST nodes -------------------------===//
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.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_TEXTNODEDUMPER_H
14#define LLVM_CLANG_AST_TEXTNODEDUMPER_H
15
16#include "clang/AST/ASTContext.h"
17#include "clang/AST/ASTDumperUtils.h"
18#include "clang/AST/AttrVisitor.h"
19#include "clang/AST/CommentCommandTraits.h"
20#include "clang/AST/CommentVisitor.h"
21#include "clang/AST/DeclVisitor.h"
22#include "clang/AST/ExprCXX.h"
23#include "clang/AST/StmtVisitor.h"
24#include "clang/AST/TemplateArgumentVisitor.h"
25#include "clang/AST/Type.h"
26#include "clang/AST/TypeVisitor.h"
27
28namespace clang {
29
30class APValue;
31
32class TextTreeStructure {
33  raw_ostream &OS;
34  const bool ShowColors;
35
36  /// Pending[i] is an action to dump an entity at level i.
37  llvm::SmallVector<std::function<void(bool IsLastChild)>, 32> Pending;
38
39  /// Indicates whether we're at the top level.
40  bool TopLevel = true;
41
42  /// Indicates if we're handling the first child after entering a new depth.
43  bool FirstChild = true;
44
45  /// Prefix for currently-being-dumped entity.
46  std::string Prefix;
47
48public:
49  /// Add a child of the current node.  Calls DoAddChild without arguments
50  template <typename Fn> void AddChild(Fn DoAddChild) {
51    return AddChild("", DoAddChild);
52  }
53
54  /// Add a child of the current node with an optional label.
55  /// Calls DoAddChild without arguments.
56  template <typename Fn> void AddChild(StringRef Label, Fn DoAddChild) {
57    // If we're at the top level, there's nothing interesting to do; just
58    // run the dumper.
59    if (TopLevel) {
60      TopLevel = false;
61      DoAddChild();
62      while (!Pending.empty()) {
63        Pending.back()(true);
64        Pending.pop_back();
65      }
66      Prefix.clear();
67      OS << "\n";
68      TopLevel = true;
69      return;
70    }
71
72    // We need to capture an owning-string in the lambda because the lambda
73    // is invoked in a deferred manner.
74    std::string LabelStr(Label);
75    auto DumpWithIndent = [this, DoAddChild, LabelStr](bool IsLastChild) {
76      // Print out the appropriate tree structure and work out the prefix for
77      // children of this node. For instance:
78      //
79      //   A        Prefix = ""
80      //   |-B      Prefix = "| "
81      //   | `-C    Prefix = "|   "
82      //   `-D      Prefix = "  "
83      //     |-E    Prefix = "  | "
84      //     `-F    Prefix = "    "
85      //   G        Prefix = ""
86      //
87      // Note that the first level gets no prefix.
88      {
89        OS << '\n';
90        ColorScope Color(OS, ShowColors, IndentColor);
91        OS << Prefix << (IsLastChild ? '`' : '|') << '-';
92        if (!LabelStr.empty())
93          OS << LabelStr << ": ";
94
95        this->Prefix.push_back(IsLastChild ? ' ' : '|');
96        this->Prefix.push_back(' ');
97      }
98
99      FirstChild = true;
100      unsigned Depth = Pending.size();
101
102      DoAddChild();
103
104      // If any children are left, they're the last at their nesting level.
105      // Dump those ones out now.
106      while (Depth < Pending.size()) {
107        Pending.back()(true);
108        this->Pending.pop_back();
109      }
110
111      // Restore the old prefix.
112      this->Prefix.resize(Prefix.size() - 2);
113    };
114
115    if (FirstChild) {
116      Pending.push_back(std::move(DumpWithIndent));
117    } else {
118      Pending.back()(false);
119      Pending.back() = std::move(DumpWithIndent);
120    }
121    FirstChild = false;
122  }
123
124  TextTreeStructure(raw_ostream &OS, bool ShowColors)
125      : OS(OS), ShowColors(ShowColors) {}
126};
127
128class TextNodeDumper
129    : public TextTreeStructure,
130      public comments::ConstCommentVisitor<TextNodeDumper, void,
131                                           const comments::FullComment *>,
132      public ConstAttrVisitor<TextNodeDumper>,
133      public ConstTemplateArgumentVisitor<TextNodeDumper>,
134      public ConstStmtVisitor<TextNodeDumper>,
135      public TypeVisitor<TextNodeDumper>,
136      public ConstDeclVisitor<TextNodeDumper> {
137  raw_ostream &OS;
138  const bool ShowColors;
139
140  /// Keep track of the last location we print out so that we can
141  /// print out deltas from then on out.
142  const char *LastLocFilename = "";
143  unsigned LastLocLine = ~0U;
144
145  /// \p Context, \p SM, and \p Traits can be null. This is because we want
146  /// to be able to call \p dump() in a debugger without having to pass the
147  /// \p ASTContext to \p dump. Not all parts of the AST dump output will be
148  /// available without the \p ASTContext.
149  const ASTContext *Context = nullptr;
150  const SourceManager *SM = nullptr;
151
152  /// The policy to use for printing; can be defaulted.
153  PrintingPolicy PrintPolicy = LangOptions();
154
155  const comments::CommandTraits *Traits = nullptr;
156
157  const char *getCommandName(unsigned CommandID);
158
159  void dumpAPValueChildren(const APValue &Value, QualType Ty,
160                           const APValue &(*IdxToChildFun)(const APValue &,
161                                                           unsigned),
162                           unsigned NumChildren, StringRef LabelSingular,
163                           StringRef LabelPlurial);
164
165public:
166  TextNodeDumper(raw_ostream &OS, const ASTContext &Context, bool ShowColors);
167  TextNodeDumper(raw_ostream &OS, bool ShowColors);
168
169  void Visit(const comments::Comment *C, const comments::FullComment *FC);
170
171  void Visit(const Attr *A);
172
173  void Visit(const TemplateArgument &TA, SourceRange R,
174             const Decl *From = nullptr, StringRef Label = {});
175
176  void Visit(const Stmt *Node);
177
178  void Visit(const Type *T);
179
180  void Visit(QualType T);
181
182  void Visit(const Decl *D);
183
184  void Visit(const CXXCtorInitializer *Init);
185
186  void Visit(const OMPClause *C);
187
188  void Visit(const BlockDecl::Capture &C);
189
190  void Visit(const GenericSelectionExpr::ConstAssociation &A);
191
192  void Visit(const APValue &Value, QualType Ty);
193
194  void dumpPointer(const void *Ptr);
195  void dumpLocation(SourceLocation Loc);
196  void dumpSourceRange(SourceRange R);
197  void dumpBareType(QualType T, bool Desugar = true);
198  void dumpType(QualType T);
199  void dumpBareDeclRef(const Decl *D);
200  void dumpName(const NamedDecl *ND);
201  void dumpAccessSpecifier(AccessSpecifier AS);
202  void dumpCleanupObject(const ExprWithCleanups::CleanupObject &C);
203
204  void dumpDeclRef(const Decl *D, StringRef Label = {});
205
206  void visitTextComment(const comments::TextComment *C,
207                        const comments::FullComment *);
208  void visitInlineCommandComment(const comments::InlineCommandComment *C,
209                                 const comments::FullComment *);
210  void visitHTMLStartTagComment(const comments::HTMLStartTagComment *C,
211                                const comments::FullComment *);
212  void visitHTMLEndTagComment(const comments::HTMLEndTagComment *C,
213                              const comments::FullComment *);
214  void visitBlockCommandComment(const comments::BlockCommandComment *C,
215                                const comments::FullComment *);
216  void visitParamCommandComment(const comments::ParamCommandComment *C,
217                                const comments::FullComment *FC);
218  void visitTParamCommandComment(const comments::TParamCommandComment *C,
219                                 const comments::FullComment *FC);
220  void visitVerbatimBlockComment(const comments::VerbatimBlockComment *C,
221                                 const comments::FullComment *);
222  void
223  visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment *C,
224                                const comments::FullComment *);
225  void visitVerbatimLineComment(const comments::VerbatimLineComment *C,
226                                const comments::FullComment *);
227
228// Implements Visit methods for Attrs.
229#include "clang/AST/AttrTextNodeDump.inc"
230
231  void VisitNullTemplateArgument(const TemplateArgument &TA);
232  void VisitTypeTemplateArgument(const TemplateArgument &TA);
233  void VisitDeclarationTemplateArgument(const TemplateArgument &TA);
234  void VisitNullPtrTemplateArgument(const TemplateArgument &TA);
235  void VisitIntegralTemplateArgument(const TemplateArgument &TA);
236  void VisitTemplateTemplateArgument(const TemplateArgument &TA);
237  void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA);
238  void VisitExpressionTemplateArgument(const TemplateArgument &TA);
239  void VisitPackTemplateArgument(const TemplateArgument &TA);
240
241  void VisitIfStmt(const IfStmt *Node);
242  void VisitSwitchStmt(const SwitchStmt *Node);
243  void VisitWhileStmt(const WhileStmt *Node);
244  void VisitLabelStmt(const LabelStmt *Node);
245  void VisitGotoStmt(const GotoStmt *Node);
246  void VisitCaseStmt(const CaseStmt *Node);
247  void VisitConstantExpr(const ConstantExpr *Node);
248  void VisitCallExpr(const CallExpr *Node);
249  void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node);
250  void VisitCastExpr(const CastExpr *Node);
251  void VisitImplicitCastExpr(const ImplicitCastExpr *Node);
252  void VisitDeclRefExpr(const DeclRefExpr *Node);
253  void VisitPredefinedExpr(const PredefinedExpr *Node);
254  void VisitCharacterLiteral(const CharacterLiteral *Node);
255  void VisitIntegerLiteral(const IntegerLiteral *Node);
256  void VisitFixedPointLiteral(const FixedPointLiteral *Node);
257  void VisitFloatingLiteral(const FloatingLiteral *Node);
258  void VisitStringLiteral(const StringLiteral *Str);
259  void VisitInitListExpr(const InitListExpr *ILE);
260  void VisitGenericSelectionExpr(const GenericSelectionExpr *E);
261  void VisitUnaryOperator(const UnaryOperator *Node);
262  void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node);
263  void VisitMemberExpr(const MemberExpr *Node);
264  void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node);
265  void VisitBinaryOperator(const BinaryOperator *Node);
266  void VisitCompoundAssignOperator(const CompoundAssignOperator *Node);
267  void VisitAddrLabelExpr(const AddrLabelExpr *Node);
268  void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node);
269  void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node);
270  void VisitCXXThisExpr(const CXXThisExpr *Node);
271  void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node);
272  void VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr *Node);
273  void VisitCXXConstructExpr(const CXXConstructExpr *Node);
274  void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node);
275  void VisitCXXNewExpr(const CXXNewExpr *Node);
276  void VisitCXXDeleteExpr(const CXXDeleteExpr *Node);
277  void VisitTypeTraitExpr(const TypeTraitExpr *Node);
278  void VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *Node);
279  void VisitExpressionTraitExpr(const ExpressionTraitExpr *Node);
280  void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
281  void VisitExprWithCleanups(const ExprWithCleanups *Node);
282  void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
283  void VisitSizeOfPackExpr(const SizeOfPackExpr *Node);
284  void
285  VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *Node);
286  void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node);
287  void VisitObjCEncodeExpr(const ObjCEncodeExpr *Node);
288  void VisitObjCMessageExpr(const ObjCMessageExpr *Node);
289  void VisitObjCBoxedExpr(const ObjCBoxedExpr *Node);
290  void VisitObjCSelectorExpr(const ObjCSelectorExpr *Node);
291  void VisitObjCProtocolExpr(const ObjCProtocolExpr *Node);
292  void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node);
293  void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node);
294  void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node);
295  void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node);
296  void VisitOMPIteratorExpr(const OMPIteratorExpr *Node);
297
298  void VisitRValueReferenceType(const ReferenceType *T);
299  void VisitArrayType(const ArrayType *T);
300  void VisitConstantArrayType(const ConstantArrayType *T);
301  void VisitVariableArrayType(const VariableArrayType *T);
302  void VisitDependentSizedArrayType(const DependentSizedArrayType *T);
303  void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T);
304  void VisitVectorType(const VectorType *T);
305  void VisitFunctionType(const FunctionType *T);
306  void VisitFunctionProtoType(const FunctionProtoType *T);
307  void VisitUnresolvedUsingType(const UnresolvedUsingType *T);
308  void VisitTypedefType(const TypedefType *T);
309  void VisitUnaryTransformType(const UnaryTransformType *T);
310  void VisitTagType(const TagType *T);
311  void VisitTemplateTypeParmType(const TemplateTypeParmType *T);
312  void VisitAutoType(const AutoType *T);
313  void VisitTemplateSpecializationType(const TemplateSpecializationType *T);
314  void VisitInjectedClassNameType(const InjectedClassNameType *T);
315  void VisitObjCInterfaceType(const ObjCInterfaceType *T);
316  void VisitPackExpansionType(const PackExpansionType *T);
317
318  void VisitLabelDecl(const LabelDecl *D);
319  void VisitTypedefDecl(const TypedefDecl *D);
320  void VisitEnumDecl(const EnumDecl *D);
321  void VisitRecordDecl(const RecordDecl *D);
322  void VisitEnumConstantDecl(const EnumConstantDecl *D);
323  void VisitIndirectFieldDecl(const IndirectFieldDecl *D);
324  void VisitFunctionDecl(const FunctionDecl *D);
325  void VisitFieldDecl(const FieldDecl *D);
326  void VisitVarDecl(const VarDecl *D);
327  void VisitBindingDecl(const BindingDecl *D);
328  void VisitCapturedDecl(const CapturedDecl *D);
329  void VisitImportDecl(const ImportDecl *D);
330  void VisitPragmaCommentDecl(const PragmaCommentDecl *D);
331  void VisitPragmaDetectMismatchDecl(const PragmaDetectMismatchDecl *D);
332  void VisitOMPExecutableDirective(const OMPExecutableDirective *D);
333  void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D);
334  void VisitOMPRequiresDecl(const OMPRequiresDecl *D);
335  void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D);
336  void VisitNamespaceDecl(const NamespaceDecl *D);
337  void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D);
338  void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);
339  void VisitTypeAliasDecl(const TypeAliasDecl *D);
340  void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D);
341  void VisitCXXRecordDecl(const CXXRecordDecl *D);
342  void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
343  void VisitClassTemplateDecl(const ClassTemplateDecl *D);
344  void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D);
345  void VisitVarTemplateDecl(const VarTemplateDecl *D);
346  void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
347  void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
348  void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
349  void VisitUsingDecl(const UsingDecl *D);
350  void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
351  void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
352  void VisitUsingShadowDecl(const UsingShadowDecl *D);
353  void VisitConstructorUsingShadowDecl(const ConstructorUsingShadowDecl *D);
354  void VisitLinkageSpecDecl(const LinkageSpecDecl *D);
355  void VisitAccessSpecDecl(const AccessSpecDecl *D);
356  void VisitFriendDecl(const FriendDecl *D);
357  void VisitObjCIvarDecl(const ObjCIvarDecl *D);
358  void VisitObjCMethodDecl(const ObjCMethodDecl *D);
359  void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D);
360  void VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
361  void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D);
362  void VisitObjCProtocolDecl(const ObjCProtocolDecl *D);
363  void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D);
364  void VisitObjCImplementationDecl(const ObjCImplementationDecl *D);
365  void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D);
366  void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
367  void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
368  void VisitBlockDecl(const BlockDecl *D);
369  void VisitConceptDecl(const ConceptDecl *D);
370  void
371  VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
372};
373
374} // namespace clang
375
376#endif // LLVM_CLANG_AST_TEXTNODEDUMPER_H
377