Home | History | Annotate | Line # | Download | only in AST
      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 
     28 namespace clang {
     29 
     30 class APValue;
     31 
     32 class 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 
     48 public:
     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     auto DumpWithIndent = [this, DoAddChild,
     73                            Label(Label.str())](bool IsLastChild) {
     74       // Print out the appropriate tree structure and work out the prefix for
     75       // children of this node. For instance:
     76       //
     77       //   A        Prefix = ""
     78       //   |-B      Prefix = "| "
     79       //   | `-C    Prefix = "|   "
     80       //   `-D      Prefix = "  "
     81       //     |-E    Prefix = "  | "
     82       //     `-F    Prefix = "    "
     83       //   G        Prefix = ""
     84       //
     85       // Note that the first level gets no prefix.
     86       {
     87         OS << '\n';
     88         ColorScope Color(OS, ShowColors, IndentColor);
     89         OS << Prefix << (IsLastChild ? '`' : '|') << '-';
     90         if (!Label.empty())
     91           OS << Label << ": ";
     92 
     93         this->Prefix.push_back(IsLastChild ? ' ' : '|');
     94         this->Prefix.push_back(' ');
     95       }
     96 
     97       FirstChild = true;
     98       unsigned Depth = Pending.size();
     99 
    100       DoAddChild();
    101 
    102       // If any children are left, they're the last at their nesting level.
    103       // Dump those ones out now.
    104       while (Depth < Pending.size()) {
    105         Pending.back()(true);
    106         this->Pending.pop_back();
    107       }
    108 
    109       // Restore the old prefix.
    110       this->Prefix.resize(Prefix.size() - 2);
    111     };
    112 
    113     if (FirstChild) {
    114       Pending.push_back(std::move(DumpWithIndent));
    115     } else {
    116       Pending.back()(false);
    117       Pending.back() = std::move(DumpWithIndent);
    118     }
    119     FirstChild = false;
    120   }
    121 
    122   TextTreeStructure(raw_ostream &OS, bool ShowColors)
    123       : OS(OS), ShowColors(ShowColors) {}
    124 };
    125 
    126 class TextNodeDumper
    127     : public TextTreeStructure,
    128       public comments::ConstCommentVisitor<TextNodeDumper, void,
    129                                            const comments::FullComment *>,
    130       public ConstAttrVisitor<TextNodeDumper>,
    131       public ConstTemplateArgumentVisitor<TextNodeDumper>,
    132       public ConstStmtVisitor<TextNodeDumper>,
    133       public TypeVisitor<TextNodeDumper>,
    134       public ConstDeclVisitor<TextNodeDumper> {
    135   raw_ostream &OS;
    136   const bool ShowColors;
    137 
    138   /// Keep track of the last location we print out so that we can
    139   /// print out deltas from then on out.
    140   const char *LastLocFilename = "";
    141   unsigned LastLocLine = ~0U;
    142 
    143   /// \p Context, \p SM, and \p Traits can be null. This is because we want
    144   /// to be able to call \p dump() in a debugger without having to pass the
    145   /// \p ASTContext to \p dump. Not all parts of the AST dump output will be
    146   /// available without the \p ASTContext.
    147   const ASTContext *Context = nullptr;
    148   const SourceManager *SM = nullptr;
    149 
    150   /// The policy to use for printing; can be defaulted.
    151   PrintingPolicy PrintPolicy = LangOptions();
    152 
    153   const comments::CommandTraits *Traits = nullptr;
    154 
    155   const char *getCommandName(unsigned CommandID);
    156   void printFPOptions(FPOptionsOverride FPO);
    157 
    158   void dumpAPValueChildren(const APValue &Value, QualType Ty,
    159                            const APValue &(*IdxToChildFun)(const APValue &,
    160                                                            unsigned),
    161                            unsigned NumChildren, StringRef LabelSingular,
    162                            StringRef LabelPlurial);
    163 
    164 public:
    165   TextNodeDumper(raw_ostream &OS, const ASTContext &Context, bool ShowColors);
    166   TextNodeDumper(raw_ostream &OS, bool ShowColors);
    167 
    168   void Visit(const comments::Comment *C, const comments::FullComment *FC);
    169 
    170   void Visit(const Attr *A);
    171 
    172   void Visit(const TemplateArgument &TA, SourceRange R,
    173              const Decl *From = nullptr, StringRef Label = {});
    174 
    175   void Visit(const Stmt *Node);
    176 
    177   void Visit(const Type *T);
    178 
    179   void Visit(QualType T);
    180 
    181   void Visit(const Decl *D);
    182 
    183   void Visit(const CXXCtorInitializer *Init);
    184 
    185   void Visit(const OMPClause *C);
    186 
    187   void Visit(const BlockDecl::Capture &C);
    188 
    189   void Visit(const GenericSelectionExpr::ConstAssociation &A);
    190 
    191   void Visit(const APValue &Value, QualType Ty);
    192 
    193   void dumpPointer(const void *Ptr);
    194   void dumpLocation(SourceLocation Loc);
    195   void dumpSourceRange(SourceRange R);
    196   void dumpBareType(QualType T, bool Desugar = true);
    197   void dumpType(QualType T);
    198   void dumpBareDeclRef(const Decl *D);
    199   void dumpName(const NamedDecl *ND);
    200   void dumpAccessSpecifier(AccessSpecifier AS);
    201   void dumpCleanupObject(const ExprWithCleanups::CleanupObject &C);
    202 
    203   void dumpDeclRef(const Decl *D, StringRef Label = {});
    204 
    205   void visitTextComment(const comments::TextComment *C,
    206                         const comments::FullComment *);
    207   void visitInlineCommandComment(const comments::InlineCommandComment *C,
    208                                  const comments::FullComment *);
    209   void visitHTMLStartTagComment(const comments::HTMLStartTagComment *C,
    210                                 const comments::FullComment *);
    211   void visitHTMLEndTagComment(const comments::HTMLEndTagComment *C,
    212                               const comments::FullComment *);
    213   void visitBlockCommandComment(const comments::BlockCommandComment *C,
    214                                 const comments::FullComment *);
    215   void visitParamCommandComment(const comments::ParamCommandComment *C,
    216                                 const comments::FullComment *FC);
    217   void visitTParamCommandComment(const comments::TParamCommandComment *C,
    218                                  const comments::FullComment *FC);
    219   void visitVerbatimBlockComment(const comments::VerbatimBlockComment *C,
    220                                  const comments::FullComment *);
    221   void
    222   visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment *C,
    223                                 const comments::FullComment *);
    224   void visitVerbatimLineComment(const comments::VerbatimLineComment *C,
    225                                 const comments::FullComment *);
    226 
    227 // Implements Visit methods for Attrs.
    228 #include "clang/AST/AttrTextNodeDump.inc"
    229 
    230   void VisitNullTemplateArgument(const TemplateArgument &TA);
    231   void VisitTypeTemplateArgument(const TemplateArgument &TA);
    232   void VisitDeclarationTemplateArgument(const TemplateArgument &TA);
    233   void VisitNullPtrTemplateArgument(const TemplateArgument &TA);
    234   void VisitIntegralTemplateArgument(const TemplateArgument &TA);
    235   void VisitTemplateTemplateArgument(const TemplateArgument &TA);
    236   void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA);
    237   void VisitExpressionTemplateArgument(const TemplateArgument &TA);
    238   void VisitPackTemplateArgument(const TemplateArgument &TA);
    239 
    240   void VisitIfStmt(const IfStmt *Node);
    241   void VisitSwitchStmt(const SwitchStmt *Node);
    242   void VisitWhileStmt(const WhileStmt *Node);
    243   void VisitLabelStmt(const LabelStmt *Node);
    244   void VisitGotoStmt(const GotoStmt *Node);
    245   void VisitCaseStmt(const CaseStmt *Node);
    246   void VisitConstantExpr(const ConstantExpr *Node);
    247   void VisitCallExpr(const CallExpr *Node);
    248   void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node);
    249   void VisitCastExpr(const CastExpr *Node);
    250   void VisitImplicitCastExpr(const ImplicitCastExpr *Node);
    251   void VisitDeclRefExpr(const DeclRefExpr *Node);
    252   void VisitPredefinedExpr(const PredefinedExpr *Node);
    253   void VisitCharacterLiteral(const CharacterLiteral *Node);
    254   void VisitIntegerLiteral(const IntegerLiteral *Node);
    255   void VisitFixedPointLiteral(const FixedPointLiteral *Node);
    256   void VisitFloatingLiteral(const FloatingLiteral *Node);
    257   void VisitStringLiteral(const StringLiteral *Str);
    258   void VisitInitListExpr(const InitListExpr *ILE);
    259   void VisitGenericSelectionExpr(const GenericSelectionExpr *E);
    260   void VisitUnaryOperator(const UnaryOperator *Node);
    261   void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node);
    262   void VisitMemberExpr(const MemberExpr *Node);
    263   void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node);
    264   void VisitBinaryOperator(const BinaryOperator *Node);
    265   void VisitCompoundAssignOperator(const CompoundAssignOperator *Node);
    266   void VisitAddrLabelExpr(const AddrLabelExpr *Node);
    267   void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node);
    268   void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node);
    269   void VisitCXXThisExpr(const CXXThisExpr *Node);
    270   void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node);
    271   void VisitCXXStaticCastExpr(const CXXStaticCastExpr *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   void VisitConceptSpecializationExpr(const ConceptSpecializationExpr *Node);
    298 
    299   void VisitRValueReferenceType(const ReferenceType *T);
    300   void VisitArrayType(const ArrayType *T);
    301   void VisitConstantArrayType(const ConstantArrayType *T);
    302   void VisitVariableArrayType(const VariableArrayType *T);
    303   void VisitDependentSizedArrayType(const DependentSizedArrayType *T);
    304   void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T);
    305   void VisitVectorType(const VectorType *T);
    306   void VisitFunctionType(const FunctionType *T);
    307   void VisitFunctionProtoType(const FunctionProtoType *T);
    308   void VisitUnresolvedUsingType(const UnresolvedUsingType *T);
    309   void VisitTypedefType(const TypedefType *T);
    310   void VisitUnaryTransformType(const UnaryTransformType *T);
    311   void VisitTagType(const TagType *T);
    312   void VisitTemplateTypeParmType(const TemplateTypeParmType *T);
    313   void VisitAutoType(const AutoType *T);
    314   void VisitTemplateSpecializationType(const TemplateSpecializationType *T);
    315   void VisitInjectedClassNameType(const InjectedClassNameType *T);
    316   void VisitObjCInterfaceType(const ObjCInterfaceType *T);
    317   void VisitPackExpansionType(const PackExpansionType *T);
    318 
    319   void VisitLabelDecl(const LabelDecl *D);
    320   void VisitTypedefDecl(const TypedefDecl *D);
    321   void VisitEnumDecl(const EnumDecl *D);
    322   void VisitRecordDecl(const RecordDecl *D);
    323   void VisitEnumConstantDecl(const EnumConstantDecl *D);
    324   void VisitIndirectFieldDecl(const IndirectFieldDecl *D);
    325   void VisitFunctionDecl(const FunctionDecl *D);
    326   void VisitFieldDecl(const FieldDecl *D);
    327   void VisitVarDecl(const VarDecl *D);
    328   void VisitBindingDecl(const BindingDecl *D);
    329   void VisitCapturedDecl(const CapturedDecl *D);
    330   void VisitImportDecl(const ImportDecl *D);
    331   void VisitPragmaCommentDecl(const PragmaCommentDecl *D);
    332   void VisitPragmaDetectMismatchDecl(const PragmaDetectMismatchDecl *D);
    333   void VisitOMPExecutableDirective(const OMPExecutableDirective *D);
    334   void VisitOMPDeclareReductionDecl(const OMPDeclareReductionDecl *D);
    335   void VisitOMPRequiresDecl(const OMPRequiresDecl *D);
    336   void VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D);
    337   void VisitNamespaceDecl(const NamespaceDecl *D);
    338   void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D);
    339   void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);
    340   void VisitTypeAliasDecl(const TypeAliasDecl *D);
    341   void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D);
    342   void VisitCXXRecordDecl(const CXXRecordDecl *D);
    343   void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
    344   void VisitClassTemplateDecl(const ClassTemplateDecl *D);
    345   void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D);
    346   void VisitVarTemplateDecl(const VarTemplateDecl *D);
    347   void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
    348   void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
    349   void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
    350   void VisitUsingDecl(const UsingDecl *D);
    351   void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
    352   void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
    353   void VisitUsingShadowDecl(const UsingShadowDecl *D);
    354   void VisitConstructorUsingShadowDecl(const ConstructorUsingShadowDecl *D);
    355   void VisitLinkageSpecDecl(const LinkageSpecDecl *D);
    356   void VisitAccessSpecDecl(const AccessSpecDecl *D);
    357   void VisitFriendDecl(const FriendDecl *D);
    358   void VisitObjCIvarDecl(const ObjCIvarDecl *D);
    359   void VisitObjCMethodDecl(const ObjCMethodDecl *D);
    360   void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D);
    361   void VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
    362   void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D);
    363   void VisitObjCProtocolDecl(const ObjCProtocolDecl *D);
    364   void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D);
    365   void VisitObjCImplementationDecl(const ObjCImplementationDecl *D);
    366   void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D);
    367   void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
    368   void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
    369   void VisitBlockDecl(const BlockDecl *D);
    370   void VisitConceptDecl(const ConceptDecl *D);
    371   void
    372   VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
    373 };
    374 
    375 } // namespace clang
    376 
    377 #endif // LLVM_CLANG_AST_TEXTNODEDUMPER_H
    378