diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /lib/AST/ASTDumper.cpp | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/AST/ASTDumper.cpp')
-rw-r--r-- | lib/AST/ASTDumper.cpp | 1996 |
1 files changed, 1996 insertions, 0 deletions
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp new file mode 100644 index 0000000..b1d174b --- /dev/null +++ b/lib/AST/ASTDumper.cpp @@ -0,0 +1,1996 @@ +//===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the AST dump methods, which dump out the +// AST in a form that exposes type details and other fields. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" +#include "clang/AST/CommentVisitor.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/Basic/Module.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/Support/raw_ostream.h" +using namespace clang; +using namespace clang::comments; + +//===----------------------------------------------------------------------===// +// ASTDumper Visitor +//===----------------------------------------------------------------------===// + +namespace { + // Colors used for various parts of the AST dump + + struct TerminalColor { + raw_ostream::Colors Color; + bool Bold; + }; + + // Decl kind names (VarDecl, FunctionDecl, etc) + static const TerminalColor DeclKindNameColor = { raw_ostream::GREEN, true }; + // Attr names (CleanupAttr, GuardedByAttr, etc) + static const TerminalColor AttrColor = { raw_ostream::BLUE, true }; + // Statement names (DeclStmt, ImplicitCastExpr, etc) + static const TerminalColor StmtColor = { raw_ostream::MAGENTA, true }; + // Comment names (FullComment, ParagraphComment, TextComment, etc) + static const TerminalColor CommentColor = { raw_ostream::YELLOW, true }; + + // Type names (int, float, etc, plus user defined types) + static const TerminalColor TypeColor = { raw_ostream::GREEN, false }; + + // Pointer address + static const TerminalColor AddressColor = { raw_ostream::YELLOW, false }; + // Source locations + static const TerminalColor LocationColor = { raw_ostream::YELLOW, false }; + + // lvalue/xvalue + static const TerminalColor ValueKindColor = { raw_ostream::CYAN, false }; + // bitfield/objcproperty/objcsubscript/vectorcomponent + static const TerminalColor ObjectKindColor = { raw_ostream::CYAN, false }; + + // Null statements + static const TerminalColor NullColor = { raw_ostream::BLUE, false }; + + // CastKind from CastExpr's + static const TerminalColor CastColor = { raw_ostream::RED, false }; + + // Value of the statement + static const TerminalColor ValueColor = { raw_ostream::CYAN, true }; + // Decl names + static const TerminalColor DeclNameColor = { raw_ostream::CYAN, true }; + + // Indents ( `, -. | ) + static const TerminalColor IndentColor = { raw_ostream::BLUE, false }; + + class ASTDumper + : public ConstDeclVisitor<ASTDumper>, public ConstStmtVisitor<ASTDumper>, + public ConstCommentVisitor<ASTDumper> { + raw_ostream &OS; + const CommandTraits *Traits; + const SourceManager *SM; + bool IsFirstLine; + + // Indicates whether more child are expected at the current tree depth + enum IndentType { IT_Child, IT_LastChild }; + + /// Indents[i] indicates if another child exists at level i. + /// Used by Indent() to print the tree structure. + llvm::SmallVector<IndentType, 32> Indents; + + /// Indicates that more children will be needed at this indent level. + /// If true, prevents lastChild() from marking the node as the last child. + /// This is used when there are multiple collections of children to be + /// dumped as well as during conditional node dumping. + bool MoreChildren; + + /// Keep track of the last location we print out so that we can + /// print out deltas from then on out. + const char *LastLocFilename; + unsigned LastLocLine; + + /// The \c FullComment parent of the comment being dumped. + const FullComment *FC; + + bool ShowColors; + + class IndentScope { + ASTDumper &Dumper; + // Preserve the Dumper's MoreChildren value from the previous IndentScope + bool MoreChildren; + public: + IndentScope(ASTDumper &Dumper) : Dumper(Dumper) { + MoreChildren = Dumper.hasMoreChildren(); + Dumper.setMoreChildren(false); + Dumper.indent(); + } + ~IndentScope() { + Dumper.setMoreChildren(MoreChildren); + Dumper.unindent(); + } + }; + + class ColorScope { + ASTDumper &Dumper; + public: + ColorScope(ASTDumper &Dumper, TerminalColor Color) + : Dumper(Dumper) { + if (Dumper.ShowColors) + Dumper.OS.changeColor(Color.Color, Color.Bold); + } + ~ColorScope() { + if (Dumper.ShowColors) + Dumper.OS.resetColor(); + } + }; + + public: + ASTDumper(raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM) + : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false), + LastLocFilename(""), LastLocLine(~0U), FC(0), + ShowColors(SM && SM->getDiagnostics().getShowColors()) { } + + ASTDumper(raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM, bool ShowColors) + : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false), + LastLocFilename(""), LastLocLine(~0U), + ShowColors(ShowColors) { } + + ~ASTDumper() { + OS << "\n"; + } + + void dumpDecl(const Decl *D); + void dumpStmt(const Stmt *S); + void dumpFullComment(const FullComment *C); + + // Formatting + void indent(); + void unindent(); + void lastChild(); + bool hasMoreChildren(); + void setMoreChildren(bool Value); + + // Utilities + void dumpPointer(const void *Ptr); + void dumpSourceRange(SourceRange R); + void dumpLocation(SourceLocation Loc); + void dumpBareType(QualType T); + void dumpType(QualType T); + void dumpBareDeclRef(const Decl *Node); + void dumpDeclRef(const Decl *Node, const char *Label = 0); + void dumpName(const NamedDecl *D); + bool hasNodes(const DeclContext *DC); + void dumpDeclContext(const DeclContext *DC); + void dumpAttr(const Attr *A); + + // C++ Utilities + void dumpAccessSpecifier(AccessSpecifier AS); + void dumpCXXCtorInitializer(const CXXCtorInitializer *Init); + void dumpTemplateParameters(const TemplateParameterList *TPL); + void dumpTemplateArgumentListInfo(const TemplateArgumentListInfo &TALI); + void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A); + void dumpTemplateArgumentList(const TemplateArgumentList &TAL); + void dumpTemplateArgument(const TemplateArgument &A, + SourceRange R = SourceRange()); + + // Decls + void VisitLabelDecl(const LabelDecl *D); + void VisitTypedefDecl(const TypedefDecl *D); + void VisitEnumDecl(const EnumDecl *D); + void VisitRecordDecl(const RecordDecl *D); + void VisitEnumConstantDecl(const EnumConstantDecl *D); + void VisitIndirectFieldDecl(const IndirectFieldDecl *D); + void VisitFunctionDecl(const FunctionDecl *D); + void VisitFieldDecl(const FieldDecl *D); + void VisitVarDecl(const VarDecl *D); + void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D); + void VisitImportDecl(const ImportDecl *D); + + // C++ Decls + void VisitNamespaceDecl(const NamespaceDecl *D); + void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D); + void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); + void VisitTypeAliasDecl(const TypeAliasDecl *D); + void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D); + void VisitCXXRecordDecl(const CXXRecordDecl *D); + void VisitStaticAssertDecl(const StaticAssertDecl *D); + void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); + void VisitClassTemplateDecl(const ClassTemplateDecl *D); + void VisitClassTemplateSpecializationDecl( + const ClassTemplateSpecializationDecl *D); + void VisitClassTemplatePartialSpecializationDecl( + const ClassTemplatePartialSpecializationDecl *D); + void VisitClassScopeFunctionSpecializationDecl( + const ClassScopeFunctionSpecializationDecl *D); + void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); + void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); + void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); + void VisitUsingDecl(const UsingDecl *D); + void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D); + void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D); + void VisitUsingShadowDecl(const UsingShadowDecl *D); + void VisitLinkageSpecDecl(const LinkageSpecDecl *D); + void VisitAccessSpecDecl(const AccessSpecDecl *D); + void VisitFriendDecl(const FriendDecl *D); + + // ObjC Decls + void VisitObjCIvarDecl(const ObjCIvarDecl *D); + void VisitObjCMethodDecl(const ObjCMethodDecl *D); + void VisitObjCCategoryDecl(const ObjCCategoryDecl *D); + void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D); + void VisitObjCProtocolDecl(const ObjCProtocolDecl *D); + void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D); + void VisitObjCImplementationDecl(const ObjCImplementationDecl *D); + void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D); + void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); + void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); + void VisitBlockDecl(const BlockDecl *D); + + // Stmts. + void VisitStmt(const Stmt *Node); + void VisitDeclStmt(const DeclStmt *Node); + void VisitAttributedStmt(const AttributedStmt *Node); + void VisitLabelStmt(const LabelStmt *Node); + void VisitGotoStmt(const GotoStmt *Node); + + // Exprs + void VisitExpr(const Expr *Node); + void VisitCastExpr(const CastExpr *Node); + void VisitDeclRefExpr(const DeclRefExpr *Node); + void VisitPredefinedExpr(const PredefinedExpr *Node); + void VisitCharacterLiteral(const CharacterLiteral *Node); + void VisitIntegerLiteral(const IntegerLiteral *Node); + void VisitFloatingLiteral(const FloatingLiteral *Node); + void VisitStringLiteral(const StringLiteral *Str); + void VisitUnaryOperator(const UnaryOperator *Node); + void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node); + void VisitMemberExpr(const MemberExpr *Node); + void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node); + void VisitBinaryOperator(const BinaryOperator *Node); + void VisitCompoundAssignOperator(const CompoundAssignOperator *Node); + void VisitAddrLabelExpr(const AddrLabelExpr *Node); + void VisitBlockExpr(const BlockExpr *Node); + void VisitOpaqueValueExpr(const OpaqueValueExpr *Node); + + // C++ + void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node); + void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node); + void VisitCXXThisExpr(const CXXThisExpr *Node); + void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node); + void VisitCXXConstructExpr(const CXXConstructExpr *Node); + void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node); + void VisitExprWithCleanups(const ExprWithCleanups *Node); + void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node); + void dumpCXXTemporary(const CXXTemporary *Temporary); + + // ObjC + void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node); + void VisitObjCEncodeExpr(const ObjCEncodeExpr *Node); + void VisitObjCMessageExpr(const ObjCMessageExpr *Node); + void VisitObjCBoxedExpr(const ObjCBoxedExpr *Node); + void VisitObjCSelectorExpr(const ObjCSelectorExpr *Node); + void VisitObjCProtocolExpr(const ObjCProtocolExpr *Node); + void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node); + void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node); + void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node); + void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node); + + // Comments. + const char *getCommandName(unsigned CommandID); + void dumpComment(const Comment *C); + + // Inline comments. + void visitTextComment(const TextComment *C); + void visitInlineCommandComment(const InlineCommandComment *C); + void visitHTMLStartTagComment(const HTMLStartTagComment *C); + void visitHTMLEndTagComment(const HTMLEndTagComment *C); + + // Block comments. + void visitBlockCommandComment(const BlockCommandComment *C); + void visitParamCommandComment(const ParamCommandComment *C); + void visitTParamCommandComment(const TParamCommandComment *C); + void visitVerbatimBlockComment(const VerbatimBlockComment *C); + void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C); + void visitVerbatimLineComment(const VerbatimLineComment *C); + }; +} + +//===----------------------------------------------------------------------===// +// Utilities +//===----------------------------------------------------------------------===// + +// Print out the appropriate tree structure using the Indents vector. +// Example of tree and the Indents vector at each level. +// A { } +// |-B { IT_Child } +// | `-C { IT_Child, IT_LastChild } +// `-D { IT_LastChild } +// |-E { IT_LastChild, IT_Child } +// `-F { IT_LastChild, IT_LastChild } +// Type non-last element, last element +// IT_Child "| " "|-" +// IT_LastChild " " "`-" +void ASTDumper::indent() { + if (IsFirstLine) + IsFirstLine = false; + else + OS << "\n"; + + ColorScope Color(*this, IndentColor); + for (llvm::SmallVector<IndentType, 32>::const_iterator I = Indents.begin(), + E = Indents.end(); + I != E; ++I) { + switch (*I) { + case IT_Child: + if (I == E - 1) + OS << "|-"; + else + OS << "| "; + continue; + case IT_LastChild: + if (I == E - 1) + OS << "`-"; + else + OS << " "; + continue; + } + llvm_unreachable("Invalid IndentType"); + } + Indents.push_back(IT_Child); +} + +void ASTDumper::unindent() { + Indents.pop_back(); +} + +// Call before each potential last child node is to be dumped. If MoreChildren +// is false, then this is the last child, otherwise treat as a regular node. +void ASTDumper::lastChild() { + if (!hasMoreChildren()) + Indents.back() = IT_LastChild; +} + +// MoreChildren should be set before calling another function that may print +// additional nodes to prevent conflicting final child nodes. +bool ASTDumper::hasMoreChildren() { + return MoreChildren; +} + +void ASTDumper::setMoreChildren(bool Value) { + MoreChildren = Value; +} + +void ASTDumper::dumpPointer(const void *Ptr) { + ColorScope Color(*this, AddressColor); + OS << ' ' << Ptr; +} + +void ASTDumper::dumpLocation(SourceLocation Loc) { + ColorScope Color(*this, LocationColor); + SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); + + // The general format we print out is filename:line:col, but we drop pieces + // that haven't changed since the last loc printed. + PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc); + + if (PLoc.isInvalid()) { + OS << "<invalid sloc>"; + return; + } + + if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) { + OS << PLoc.getFilename() << ':' << PLoc.getLine() + << ':' << PLoc.getColumn(); + LastLocFilename = PLoc.getFilename(); + LastLocLine = PLoc.getLine(); + } else if (PLoc.getLine() != LastLocLine) { + OS << "line" << ':' << PLoc.getLine() + << ':' << PLoc.getColumn(); + LastLocLine = PLoc.getLine(); + } else { + OS << "col" << ':' << PLoc.getColumn(); + } +} + +void ASTDumper::dumpSourceRange(SourceRange R) { + // Can't translate locations if a SourceManager isn't available. + if (!SM) + return; + + OS << " <"; + dumpLocation(R.getBegin()); + if (R.getBegin() != R.getEnd()) { + OS << ", "; + dumpLocation(R.getEnd()); + } + OS << ">"; + + // <t2.c:123:421[blah], t2.c:412:321> + +} + +void ASTDumper::dumpBareType(QualType T) { + ColorScope Color(*this, TypeColor); + + SplitQualType T_split = T.split(); + OS << "'" << QualType::getAsString(T_split) << "'"; + + if (!T.isNull()) { + // If the type is sugared, also dump a (shallow) desugared type. + SplitQualType D_split = T.getSplitDesugaredType(); + if (T_split != D_split) + OS << ":'" << QualType::getAsString(D_split) << "'"; + } +} + +void ASTDumper::dumpType(QualType T) { + OS << ' '; + dumpBareType(T); +} + +void ASTDumper::dumpBareDeclRef(const Decl *D) { + { + ColorScope Color(*this, DeclKindNameColor); + OS << D->getDeclKindName(); + } + dumpPointer(D); + + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { + ColorScope Color(*this, DeclNameColor); + OS << " '"; + ND->getDeclName().printName(OS); + OS << "'"; + } + + if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) + dumpType(VD->getType()); +} + +void ASTDumper::dumpDeclRef(const Decl *D, const char *Label) { + if (!D) + return; + + IndentScope Indent(*this); + if (Label) + OS << Label << ' '; + dumpBareDeclRef(D); +} + +void ASTDumper::dumpName(const NamedDecl *ND) { + if (ND->getDeclName()) { + ColorScope Color(*this, DeclNameColor); + OS << ' ' << ND->getNameAsString(); + } +} + +bool ASTDumper::hasNodes(const DeclContext *DC) { + if (!DC) + return false; + + return DC->decls_begin() != DC->decls_end(); +} + +void ASTDumper::dumpDeclContext(const DeclContext *DC) { + if (!DC) + return; + for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end(); + I != E; ++I) { + DeclContext::decl_iterator Next = I; + ++Next; + if (Next == E) + lastChild(); + dumpDecl(*I); + } +} + +void ASTDumper::dumpAttr(const Attr *A) { + IndentScope Indent(*this); + { + ColorScope Color(*this, AttrColor); + switch (A->getKind()) { +#define ATTR(X) case attr::X: OS << #X; break; +#include "clang/Basic/AttrList.inc" + default: llvm_unreachable("unexpected attribute kind"); + } + OS << "Attr"; + } + dumpPointer(A); + dumpSourceRange(A->getRange()); +#include "clang/AST/AttrDump.inc" +} + +static Decl *getPreviousDeclImpl(...) { + return 0; +} + +template<typename T> +static const Decl *getPreviousDeclImpl(const Redeclarable<T> *D) { + return D->getPreviousDecl(); +} + +/// Get the previous declaration in the redeclaration chain for a declaration. +static const Decl *getPreviousDecl(const Decl *D) { + switch (D->getKind()) { +#define DECL(DERIVED, BASE) \ + case Decl::DERIVED: \ + return getPreviousDeclImpl(cast<DERIVED##Decl>(D)); +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" + } + llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); +} + +//===----------------------------------------------------------------------===// +// C++ Utilities +//===----------------------------------------------------------------------===// + +void ASTDumper::dumpAccessSpecifier(AccessSpecifier AS) { + switch (AS) { + case AS_none: + break; + case AS_public: + OS << "public"; + break; + case AS_protected: + OS << "protected"; + break; + case AS_private: + OS << "private"; + break; + } +} + +void ASTDumper::dumpCXXCtorInitializer(const CXXCtorInitializer *Init) { + IndentScope Indent(*this); + OS << "CXXCtorInitializer"; + if (Init->isAnyMemberInitializer()) { + OS << ' '; + dumpBareDeclRef(Init->getAnyMember()); + } else { + dumpType(QualType(Init->getBaseClass(), 0)); + } + dumpStmt(Init->getInit()); +} + +void ASTDumper::dumpTemplateParameters(const TemplateParameterList *TPL) { + if (!TPL) + return; + + for (TemplateParameterList::const_iterator I = TPL->begin(), E = TPL->end(); + I != E; ++I) + dumpDecl(*I); +} + +void ASTDumper::dumpTemplateArgumentListInfo( + const TemplateArgumentListInfo &TALI) { + for (unsigned i = 0, e = TALI.size(); i < e; ++i) { + if (i + 1 == e) + lastChild(); + dumpTemplateArgumentLoc(TALI[i]); + } +} + +void ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A) { + dumpTemplateArgument(A.getArgument(), A.getSourceRange()); +} + +void ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) { + for (unsigned i = 0, e = TAL.size(); i < e; ++i) + dumpTemplateArgument(TAL[i]); +} + +void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) { + IndentScope Indent(*this); + OS << "TemplateArgument"; + if (R.isValid()) + dumpSourceRange(R); + + switch (A.getKind()) { + case TemplateArgument::Null: + OS << " null"; + break; + case TemplateArgument::Type: + OS << " type"; + lastChild(); + dumpType(A.getAsType()); + break; + case TemplateArgument::Declaration: + OS << " decl"; + lastChild(); + dumpDeclRef(A.getAsDecl()); + break; + case TemplateArgument::NullPtr: + OS << " nullptr"; + break; + case TemplateArgument::Integral: + OS << " integral " << A.getAsIntegral(); + break; + case TemplateArgument::Template: + OS << " template "; + A.getAsTemplate().dump(OS); + break; + case TemplateArgument::TemplateExpansion: + OS << " template expansion"; + A.getAsTemplateOrTemplatePattern().dump(OS); + break; + case TemplateArgument::Expression: + OS << " expr"; + lastChild(); + dumpStmt(A.getAsExpr()); + break; + case TemplateArgument::Pack: + OS << " pack"; + for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpTemplateArgument(*I); + } + break; + } +} + +//===----------------------------------------------------------------------===// +// Decl dumping methods. +//===----------------------------------------------------------------------===// + +void ASTDumper::dumpDecl(const Decl *D) { + IndentScope Indent(*this); + + if (!D) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>>"; + return; + } + + { + ColorScope Color(*this, DeclKindNameColor); + OS << D->getDeclKindName() << "Decl"; + } + dumpPointer(D); + if (D->getLexicalDeclContext() != D->getDeclContext()) + OS << " parent " << cast<Decl>(D->getDeclContext()); + if (const Decl *Prev = getPreviousDecl(D)) + OS << " prev " << Prev; + dumpSourceRange(D->getSourceRange()); + + bool HasAttrs = D->attr_begin() != D->attr_end(); + bool HasComment = D->getASTContext().getCommentForDecl(D, 0); + // Decls within functions are visited by the body + bool HasDeclContext = !isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D) && + hasNodes(dyn_cast<DeclContext>(D)); + + setMoreChildren(HasAttrs || HasComment || HasDeclContext); + ConstDeclVisitor<ASTDumper>::Visit(D); + + setMoreChildren(HasComment || HasDeclContext); + for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpAttr(*I); + } + + setMoreChildren(HasDeclContext); + lastChild(); + dumpFullComment(D->getASTContext().getCommentForDecl(D, 0)); + + setMoreChildren(false); + if (HasDeclContext) + dumpDeclContext(cast<DeclContext>(D)); +} + +void ASTDumper::VisitLabelDecl(const LabelDecl *D) { + dumpName(D); +} + +void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) { + dumpName(D); + dumpType(D->getUnderlyingType()); + if (D->isModulePrivate()) + OS << " __module_private__"; +} + +void ASTDumper::VisitEnumDecl(const EnumDecl *D) { + if (D->isScoped()) { + if (D->isScopedUsingClassTag()) + OS << " class"; + else + OS << " struct"; + } + dumpName(D); + if (D->isModulePrivate()) + OS << " __module_private__"; + if (D->isFixed()) + dumpType(D->getIntegerType()); +} + +void ASTDumper::VisitRecordDecl(const RecordDecl *D) { + OS << ' ' << D->getKindName(); + dumpName(D); + if (D->isModulePrivate()) + OS << " __module_private__"; +} + +void ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (const Expr *Init = D->getInitExpr()) { + lastChild(); + dumpStmt(Init); + } +} + +void ASTDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) { + dumpName(D); + dumpType(D->getType()); + for (IndirectFieldDecl::chain_iterator I = D->chain_begin(), + E = D->chain_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDeclRef(*I); + } +} + +void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { + dumpName(D); + dumpType(D->getType()); + + StorageClass SC = D->getStorageClass(); + if (SC != SC_None) + OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); + if (D->isInlineSpecified()) + OS << " inline"; + if (D->isVirtualAsWritten()) + OS << " virtual"; + if (D->isModulePrivate()) + OS << " __module_private__"; + + if (D->isPure()) + OS << " pure"; + else if (D->isDeletedAsWritten()) + OS << " delete"; + + bool OldMoreChildren = hasMoreChildren(); + const FunctionTemplateSpecializationInfo *FTSI = + D->getTemplateSpecializationInfo(); + bool HasTemplateSpecialization = FTSI; + + bool HasNamedDecls = D->getDeclsInPrototypeScope().begin() != + D->getDeclsInPrototypeScope().end(); + + bool HasFunctionDecls = D->param_begin() != D->param_end(); + + const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D); + bool HasCtorInitializers = C && C->init_begin() != C->init_end(); + + bool HasDeclarationBody = D->doesThisDeclarationHaveABody(); + + setMoreChildren(OldMoreChildren || HasNamedDecls || HasFunctionDecls || + HasCtorInitializers || HasDeclarationBody); + if (HasTemplateSpecialization) { + lastChild(); + dumpTemplateArgumentList(*FTSI->TemplateArguments); + } + + setMoreChildren(OldMoreChildren || HasFunctionDecls || + HasCtorInitializers || HasDeclarationBody); + for (ArrayRef<NamedDecl *>::iterator + I = D->getDeclsInPrototypeScope().begin(), + E = D->getDeclsInPrototypeScope().end(); I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDecl(*I); + } + + setMoreChildren(OldMoreChildren || HasCtorInitializers || HasDeclarationBody); + for (FunctionDecl::param_const_iterator I = D->param_begin(), + E = D->param_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDecl(*I); + } + + setMoreChildren(OldMoreChildren || HasDeclarationBody); + if (HasCtorInitializers) + for (CXXConstructorDecl::init_const_iterator I = C->init_begin(), + E = C->init_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpCXXCtorInitializer(*I); + } + + setMoreChildren(OldMoreChildren); + if (HasDeclarationBody) { + lastChild(); + dumpStmt(D->getBody()); + } +} + +void ASTDumper::VisitFieldDecl(const FieldDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (D->isMutable()) + OS << " mutable"; + if (D->isModulePrivate()) + OS << " __module_private__"; + + bool OldMoreChildren = hasMoreChildren(); + bool IsBitField = D->isBitField(); + Expr *Init = D->getInClassInitializer(); + bool HasInit = Init; + + setMoreChildren(OldMoreChildren || HasInit); + if (IsBitField) { + lastChild(); + dumpStmt(D->getBitWidth()); + } + setMoreChildren(OldMoreChildren); + if (HasInit) { + lastChild(); + dumpStmt(Init); + } +} + +void ASTDumper::VisitVarDecl(const VarDecl *D) { + dumpName(D); + dumpType(D->getType()); + StorageClass SC = D->getStorageClass(); + if (SC != SC_None) + OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); + if (D->isThreadSpecified()) + OS << " __thread"; + if (D->isModulePrivate()) + OS << " __module_private__"; + if (D->isNRVOVariable()) + OS << " nrvo"; + if (D->hasInit()) { + lastChild(); + dumpStmt(D->getInit()); + } +} + +void ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) { + lastChild(); + dumpStmt(D->getAsmString()); +} + +void ASTDumper::VisitImportDecl(const ImportDecl *D) { + OS << ' ' << D->getImportedModule()->getFullModuleName(); +} + +//===----------------------------------------------------------------------===// +// C++ Declarations +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitNamespaceDecl(const NamespaceDecl *D) { + dumpName(D); + if (D->isInline()) + OS << " inline"; + if (!D->isOriginalNamespace()) + dumpDeclRef(D->getOriginalNamespace(), "original"); +} + +void ASTDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { + OS << ' '; + dumpBareDeclRef(D->getNominatedNamespace()); +} + +void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { + dumpName(D); + dumpDeclRef(D->getAliasedNamespace()); +} + +void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) { + dumpName(D); + dumpType(D->getUnderlyingType()); +} + +void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + dumpDecl(D->getTemplatedDecl()); +} + +void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { + VisitRecordDecl(D); + if (!D->isCompleteDefinition()) + return; + + for (CXXRecordDecl::base_class_const_iterator I = D->bases_begin(), + E = D->bases_end(); + I != E; ++I) { + IndentScope Indent(*this); + if (I->isVirtual()) + OS << "virtual "; + dumpAccessSpecifier(I->getAccessSpecifier()); + dumpType(I->getType()); + if (I->isPackExpansion()) + OS << "..."; + } +} + +void ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) { + dumpStmt(D->getAssertExpr()); + lastChild(); + dumpStmt(D->getMessage()); +} + +void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + dumpDecl(D->getTemplatedDecl()); + for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(), + E = D->spec_end(); + I != E; ++I) { + FunctionTemplateDecl::spec_iterator Next = I; + ++Next; + if (Next == E) + lastChild(); + switch (I->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + if (D == D->getCanonicalDecl()) + dumpDecl(*I); + else + dumpDeclRef(*I); + break; + case TSK_ExplicitSpecialization: + dumpDeclRef(*I); + break; + } + } +} + +void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + + ClassTemplateDecl::spec_iterator I = D->spec_begin(); + ClassTemplateDecl::spec_iterator E = D->spec_end(); + if (I == E) + lastChild(); + dumpDecl(D->getTemplatedDecl()); + for (; I != E; ++I) { + ClassTemplateDecl::spec_iterator Next = I; + ++Next; + if (Next == E) + lastChild(); + switch (I->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + if (D == D->getCanonicalDecl()) + dumpDecl(*I); + else + dumpDeclRef(*I); + break; + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + dumpDeclRef(*I); + break; + } + } +} + +void ASTDumper::VisitClassTemplateSpecializationDecl( + const ClassTemplateSpecializationDecl *D) { + VisitCXXRecordDecl(D); + dumpTemplateArgumentList(D->getTemplateArgs()); +} + +void ASTDumper::VisitClassTemplatePartialSpecializationDecl( + const ClassTemplatePartialSpecializationDecl *D) { + VisitClassTemplateSpecializationDecl(D); + dumpTemplateParameters(D->getTemplateParameters()); +} + +void ASTDumper::VisitClassScopeFunctionSpecializationDecl( + const ClassScopeFunctionSpecializationDecl *D) { + dumpDeclRef(D->getSpecialization()); + if (D->hasExplicitTemplateArgs()) + dumpTemplateArgumentListInfo(D->templateArgs()); +} + +void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { + if (D->wasDeclaredWithTypename()) + OS << " typename"; + else + OS << " class"; + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); + if (D->hasDefaultArgument()) + dumpType(D->getDefaultArgument()); +} + +void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { + dumpType(D->getType()); + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); + if (D->hasDefaultArgument()) + dumpStmt(D->getDefaultArgument()); +} + +void ASTDumper::VisitTemplateTemplateParmDecl( + const TemplateTemplateParmDecl *D) { + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + if (D->hasDefaultArgument()) + dumpTemplateArgumentLoc(D->getDefaultArgument()); +} + +void ASTDumper::VisitUsingDecl(const UsingDecl *D) { + OS << ' '; + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); +} + +void ASTDumper::VisitUnresolvedUsingTypenameDecl( + const UnresolvedUsingTypenameDecl *D) { + OS << ' '; + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); +} + +void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { + OS << ' '; + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); + dumpType(D->getType()); +} + +void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) { + OS << ' '; + dumpBareDeclRef(D->getTargetDecl()); +} + +void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) { + switch (D->getLanguage()) { + case LinkageSpecDecl::lang_c: OS << " C"; break; + case LinkageSpecDecl::lang_cxx: OS << " C++"; break; + } +} + +void ASTDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) { + OS << ' '; + dumpAccessSpecifier(D->getAccess()); +} + +void ASTDumper::VisitFriendDecl(const FriendDecl *D) { + lastChild(); + if (TypeSourceInfo *T = D->getFriendType()) + dumpType(T->getType()); + else + dumpDecl(D->getFriendDecl()); +} + +//===----------------------------------------------------------------------===// +// Obj-C Declarations +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (D->getSynthesize()) + OS << " synthesize"; + + switch (D->getAccessControl()) { + case ObjCIvarDecl::None: + OS << " none"; + break; + case ObjCIvarDecl::Private: + OS << " private"; + break; + case ObjCIvarDecl::Protected: + OS << " protected"; + break; + case ObjCIvarDecl::Public: + OS << " public"; + break; + case ObjCIvarDecl::Package: + OS << " package"; + break; + } +} + +void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { + if (D->isInstanceMethod()) + OS << " -"; + else + OS << " +"; + dumpName(D); + dumpType(D->getResultType()); + + bool OldMoreChildren = hasMoreChildren(); + bool IsVariadic = D->isVariadic(); + bool HasBody = D->hasBody(); + + setMoreChildren(OldMoreChildren || IsVariadic || HasBody); + if (D->isThisDeclarationADefinition()) { + lastChild(); + dumpDeclContext(D); + } else { + for (ObjCMethodDecl::param_const_iterator I = D->param_begin(), + E = D->param_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDecl(*I); + } + } + + setMoreChildren(OldMoreChildren || HasBody); + if (IsVariadic) { + lastChild(); + IndentScope Indent(*this); + OS << "..."; + } + + setMoreChildren(OldMoreChildren); + if (HasBody) { + lastChild(); + dumpStmt(D->getBody()); + } +} + +void ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { + dumpName(D); + dumpDeclRef(D->getClassInterface()); + if (D->protocol_begin() == D->protocol_end()) + lastChild(); + dumpDeclRef(D->getImplementation()); + for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(), + E = D->protocol_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDeclRef(*I); + } +} + +void ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { + dumpName(D); + dumpDeclRef(D->getClassInterface()); + lastChild(); + dumpDeclRef(D->getCategoryDecl()); +} + +void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { + dumpName(D); + for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), + E = D->protocol_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDeclRef(*I); + } +} + +void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { + dumpName(D); + dumpDeclRef(D->getSuperClass(), "super"); + if (D->protocol_begin() == D->protocol_end()) + lastChild(); + dumpDeclRef(D->getImplementation()); + for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(), + E = D->protocol_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDeclRef(*I); + } +} + +void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { + dumpName(D); + dumpDeclRef(D->getSuperClass(), "super"); + if (D->init_begin() == D->init_end()) + lastChild(); + dumpDeclRef(D->getClassInterface()); + for (ObjCImplementationDecl::init_const_iterator I = D->init_begin(), + E = D->init_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpCXXCtorInitializer(*I); + } +} + +void ASTDumper::VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D) { + dumpName(D); + lastChild(); + dumpDeclRef(D->getClassInterface()); +} + +void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { + dumpName(D); + dumpType(D->getType()); + + if (D->getPropertyImplementation() == ObjCPropertyDecl::Required) + OS << " required"; + else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional) + OS << " optional"; + + ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes(); + if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) { + if (Attrs & ObjCPropertyDecl::OBJC_PR_readonly) + OS << " readonly"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_assign) + OS << " assign"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_readwrite) + OS << " readwrite"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_retain) + OS << " retain"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_copy) + OS << " copy"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic) + OS << " nonatomic"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_atomic) + OS << " atomic"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_weak) + OS << " weak"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_strong) + OS << " strong"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) + OS << " unsafe_unretained"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) { + if (!(Attrs & ObjCPropertyDecl::OBJC_PR_setter)) + lastChild(); + dumpDeclRef(D->getGetterMethodDecl(), "getter"); + } + if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) { + lastChild(); + dumpDeclRef(D->getSetterMethodDecl(), "setter"); + } + } +} + +void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { + dumpName(D->getPropertyDecl()); + if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) + OS << " synthesize"; + else + OS << " dynamic"; + dumpDeclRef(D->getPropertyDecl()); + lastChild(); + dumpDeclRef(D->getPropertyIvarDecl()); +} + +void ASTDumper::VisitBlockDecl(const BlockDecl *D) { + for (BlockDecl::param_const_iterator I = D->param_begin(), E = D->param_end(); + I != E; ++I) + dumpDecl(*I); + + if (D->isVariadic()) { + IndentScope Indent(*this); + OS << "..."; + } + + if (D->capturesCXXThis()) { + IndentScope Indent(*this); + OS << "capture this"; + } + for (BlockDecl::capture_iterator I = D->capture_begin(), E = D->capture_end(); + I != E; ++I) { + IndentScope Indent(*this); + OS << "capture"; + if (I->isByRef()) + OS << " byref"; + if (I->isNested()) + OS << " nested"; + if (I->getVariable()) { + OS << ' '; + dumpBareDeclRef(I->getVariable()); + } + if (I->hasCopyExpr()) + dumpStmt(I->getCopyExpr()); + } + lastChild(); + dumpStmt(D->getBody()); +} + +//===----------------------------------------------------------------------===// +// Stmt dumping methods. +//===----------------------------------------------------------------------===// + +void ASTDumper::dumpStmt(const Stmt *S) { + IndentScope Indent(*this); + + if (!S) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>>"; + return; + } + + if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { + VisitDeclStmt(DS); + return; + } + + setMoreChildren(S->children()); + ConstStmtVisitor<ASTDumper>::Visit(S); + setMoreChildren(false); + for (Stmt::const_child_range CI = S->children(); CI; ++CI) { + Stmt::const_child_range Next = CI; + ++Next; + if (!Next) + lastChild(); + dumpStmt(*CI); + } +} + +void ASTDumper::VisitStmt(const Stmt *Node) { + { + ColorScope Color(*this, StmtColor); + OS << Node->getStmtClassName(); + } + dumpPointer(Node); + dumpSourceRange(Node->getSourceRange()); +} + +void ASTDumper::VisitDeclStmt(const DeclStmt *Node) { + VisitStmt(Node); + for (DeclStmt::const_decl_iterator I = Node->decl_begin(), + E = Node->decl_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpDecl(*I); + } +} + +void ASTDumper::VisitAttributedStmt(const AttributedStmt *Node) { + VisitStmt(Node); + for (ArrayRef<const Attr *>::iterator I = Node->getAttrs().begin(), + E = Node->getAttrs().end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpAttr(*I); + } +} + +void ASTDumper::VisitLabelStmt(const LabelStmt *Node) { + VisitStmt(Node); + OS << " '" << Node->getName() << "'"; +} + +void ASTDumper::VisitGotoStmt(const GotoStmt *Node) { + VisitStmt(Node); + OS << " '" << Node->getLabel()->getName() << "'"; + dumpPointer(Node->getLabel()); +} + +//===----------------------------------------------------------------------===// +// Expr dumping methods. +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitExpr(const Expr *Node) { + VisitStmt(Node); + dumpType(Node->getType()); + + { + ColorScope Color(*this, ValueKindColor); + switch (Node->getValueKind()) { + case VK_RValue: + break; + case VK_LValue: + OS << " lvalue"; + break; + case VK_XValue: + OS << " xvalue"; + break; + } + } + + { + ColorScope Color(*this, ObjectKindColor); + switch (Node->getObjectKind()) { + case OK_Ordinary: + break; + case OK_BitField: + OS << " bitfield"; + break; + case OK_ObjCProperty: + OS << " objcproperty"; + break; + case OK_ObjCSubscript: + OS << " objcsubscript"; + break; + case OK_VectorComponent: + OS << " vectorcomponent"; + break; + } + } +} + +static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) { + if (Node->path_empty()) + return; + + OS << " ("; + bool First = true; + for (CastExpr::path_const_iterator I = Node->path_begin(), + E = Node->path_end(); + I != E; ++I) { + const CXXBaseSpecifier *Base = *I; + if (!First) + OS << " -> "; + + const CXXRecordDecl *RD = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + + if (Base->isVirtual()) + OS << "virtual "; + OS << RD->getName(); + First = false; + } + + OS << ')'; +} + +void ASTDumper::VisitCastExpr(const CastExpr *Node) { + VisitExpr(Node); + OS << " <"; + { + ColorScope Color(*this, CastColor); + OS << Node->getCastKindName(); + } + dumpBasePath(OS, Node); + OS << ">"; +} + +void ASTDumper::VisitDeclRefExpr(const DeclRefExpr *Node) { + VisitExpr(Node); + + OS << " "; + dumpBareDeclRef(Node->getDecl()); + if (Node->getDecl() != Node->getFoundDecl()) { + OS << " ("; + dumpBareDeclRef(Node->getFoundDecl()); + OS << ")"; + } +} + +void ASTDumper::VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node) { + VisitExpr(Node); + OS << " ("; + if (!Node->requiresADL()) + OS << "no "; + OS << "ADL) = '" << Node->getName() << '\''; + + UnresolvedLookupExpr::decls_iterator + I = Node->decls_begin(), E = Node->decls_end(); + if (I == E) + OS << " empty"; + for (; I != E; ++I) + dumpPointer(*I); +} + +void ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) { + VisitExpr(Node); + + { + ColorScope Color(*this, DeclKindNameColor); + OS << " " << Node->getDecl()->getDeclKindName() << "Decl"; + } + OS << "='" << *Node->getDecl() << "'"; + dumpPointer(Node->getDecl()); + if (Node->isFreeIvar()) + OS << " isFreeIvar"; +} + +void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { + VisitExpr(Node); + switch (Node->getIdentType()) { + default: llvm_unreachable("unknown case"); + case PredefinedExpr::Func: OS << " __func__"; break; + case PredefinedExpr::Function: OS << " __FUNCTION__"; break; + case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break; + case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break; + } +} + +void ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) { + VisitExpr(Node); + ColorScope Color(*this, ValueColor); + OS << " " << Node->getValue(); +} + +void ASTDumper::VisitIntegerLiteral(const IntegerLiteral *Node) { + VisitExpr(Node); + + bool isSigned = Node->getType()->isSignedIntegerType(); + ColorScope Color(*this, ValueColor); + OS << " " << Node->getValue().toString(10, isSigned); +} + +void ASTDumper::VisitFloatingLiteral(const FloatingLiteral *Node) { + VisitExpr(Node); + ColorScope Color(*this, ValueColor); + OS << " " << Node->getValueAsApproximateDouble(); +} + +void ASTDumper::VisitStringLiteral(const StringLiteral *Str) { + VisitExpr(Str); + ColorScope Color(*this, ValueColor); + OS << " "; + Str->outputString(OS); +} + +void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) { + VisitExpr(Node); + OS << " " << (Node->isPostfix() ? "postfix" : "prefix") + << " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; +} + +void ASTDumper::VisitUnaryExprOrTypeTraitExpr( + const UnaryExprOrTypeTraitExpr *Node) { + VisitExpr(Node); + switch(Node->getKind()) { + case UETT_SizeOf: + OS << " sizeof"; + break; + case UETT_AlignOf: + OS << " alignof"; + break; + case UETT_VecStep: + OS << " vec_step"; + break; + } + if (Node->isArgumentType()) + dumpType(Node->getArgumentType()); +} + +void ASTDumper::VisitMemberExpr(const MemberExpr *Node) { + VisitExpr(Node); + OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl(); + dumpPointer(Node->getMemberDecl()); +} + +void ASTDumper::VisitExtVectorElementExpr(const ExtVectorElementExpr *Node) { + VisitExpr(Node); + OS << " " << Node->getAccessor().getNameStart(); +} + +void ASTDumper::VisitBinaryOperator(const BinaryOperator *Node) { + VisitExpr(Node); + OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; +} + +void ASTDumper::VisitCompoundAssignOperator( + const CompoundAssignOperator *Node) { + VisitExpr(Node); + OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) + << "' ComputeLHSTy="; + dumpBareType(Node->getComputationLHSType()); + OS << " ComputeResultTy="; + dumpBareType(Node->getComputationResultType()); +} + +void ASTDumper::VisitBlockExpr(const BlockExpr *Node) { + VisitExpr(Node); + dumpDecl(Node->getBlockDecl()); +} + +void ASTDumper::VisitOpaqueValueExpr(const OpaqueValueExpr *Node) { + VisitExpr(Node); + + if (Expr *Source = Node->getSourceExpr()) { + lastChild(); + dumpStmt(Source); + } +} + +// GNU extensions. + +void ASTDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) { + VisitExpr(Node); + OS << " " << Node->getLabel()->getName(); + dumpPointer(Node->getLabel()); +} + +//===----------------------------------------------------------------------===// +// C++ Expressions +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) { + VisitExpr(Node); + OS << " " << Node->getCastName() + << "<" << Node->getTypeAsWritten().getAsString() << ">" + << " <" << Node->getCastKindName(); + dumpBasePath(OS, Node); + OS << ">"; +} + +void ASTDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) { + VisitExpr(Node); + OS << " " << (Node->getValue() ? "true" : "false"); +} + +void ASTDumper::VisitCXXThisExpr(const CXXThisExpr *Node) { + VisitExpr(Node); + OS << " this"; +} + +void ASTDumper::VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node) { + VisitExpr(Node); + OS << " functional cast to " << Node->getTypeAsWritten().getAsString() + << " <" << Node->getCastKindName() << ">"; +} + +void ASTDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) { + VisitExpr(Node); + CXXConstructorDecl *Ctor = Node->getConstructor(); + dumpType(Ctor->getType()); + if (Node->isElidable()) + OS << " elidable"; + if (Node->requiresZeroInitialization()) + OS << " zeroing"; +} + +void ASTDumper::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node) { + VisitExpr(Node); + OS << " "; + dumpCXXTemporary(Node->getTemporary()); +} + +void ASTDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) { + VisitExpr(Node); + for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) + dumpDeclRef(Node->getObject(i), "cleanup"); +} + +void ASTDumper::dumpCXXTemporary(const CXXTemporary *Temporary) { + OS << "(CXXTemporary"; + dumpPointer(Temporary); + OS << ")"; +} + +//===----------------------------------------------------------------------===// +// Obj-C Expressions +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { + VisitExpr(Node); + OS << " selector=" << Node->getSelector().getAsString(); + switch (Node->getReceiverKind()) { + case ObjCMessageExpr::Instance: + break; + + case ObjCMessageExpr::Class: + OS << " class="; + dumpBareType(Node->getClassReceiver()); + break; + + case ObjCMessageExpr::SuperInstance: + OS << " super (instance)"; + break; + + case ObjCMessageExpr::SuperClass: + OS << " super (class)"; + break; + } +} + +void ASTDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) { + VisitExpr(Node); + OS << " selector=" << Node->getBoxingMethod()->getSelector().getAsString(); +} + +void ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { + VisitStmt(Node); + if (const VarDecl *CatchParam = Node->getCatchParamDecl()) + dumpDecl(CatchParam); + else + OS << " catch all"; +} + +void ASTDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) { + VisitExpr(Node); + dumpType(Node->getEncodedType()); +} + +void ASTDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) { + VisitExpr(Node); + + OS << " " << Node->getSelector().getAsString(); +} + +void ASTDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) { + VisitExpr(Node); + + OS << ' ' << *Node->getProtocol(); +} + +void ASTDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) { + VisitExpr(Node); + if (Node->isImplicitProperty()) { + OS << " Kind=MethodRef Getter=\""; + if (Node->getImplicitPropertyGetter()) + OS << Node->getImplicitPropertyGetter()->getSelector().getAsString(); + else + OS << "(null)"; + + OS << "\" Setter=\""; + if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter()) + OS << Setter->getSelector().getAsString(); + else + OS << "(null)"; + OS << "\""; + } else { + OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"'; + } + + if (Node->isSuperReceiver()) + OS << " super"; + + OS << " Messaging="; + if (Node->isMessagingGetter() && Node->isMessagingSetter()) + OS << "Getter&Setter"; + else if (Node->isMessagingGetter()) + OS << "Getter"; + else if (Node->isMessagingSetter()) + OS << "Setter"; +} + +void ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) { + VisitExpr(Node); + if (Node->isArraySubscriptRefExpr()) + OS << " Kind=ArraySubscript GetterForArray=\""; + else + OS << " Kind=DictionarySubscript GetterForDictionary=\""; + if (Node->getAtIndexMethodDecl()) + OS << Node->getAtIndexMethodDecl()->getSelector().getAsString(); + else + OS << "(null)"; + + if (Node->isArraySubscriptRefExpr()) + OS << "\" SetterForArray=\""; + else + OS << "\" SetterForDictionary=\""; + if (Node->setAtIndexMethodDecl()) + OS << Node->setAtIndexMethodDecl()->getSelector().getAsString(); + else + OS << "(null)"; +} + +void ASTDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) { + VisitExpr(Node); + OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no"); +} + +//===----------------------------------------------------------------------===// +// Comments +//===----------------------------------------------------------------------===// + +const char *ASTDumper::getCommandName(unsigned CommandID) { + if (Traits) + return Traits->getCommandInfo(CommandID)->Name; + const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID); + if (Info) + return Info->Name; + return "<not a builtin command>"; +} + +void ASTDumper::dumpFullComment(const FullComment *C) { + if (!C) + return; + + FC = C; + dumpComment(C); + FC = 0; +} + +void ASTDumper::dumpComment(const Comment *C) { + IndentScope Indent(*this); + + if (!C) { + ColorScope Color(*this, NullColor); + OS << "<<<NULL>>>"; + return; + } + + { + ColorScope Color(*this, CommentColor); + OS << C->getCommentKindName(); + } + dumpPointer(C); + dumpSourceRange(C->getSourceRange()); + ConstCommentVisitor<ASTDumper>::visit(C); + for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); + I != E; ++I) { + if (I + 1 == E) + lastChild(); + dumpComment(*I); + } +} + +void ASTDumper::visitTextComment(const TextComment *C) { + OS << " Text=\"" << C->getText() << "\""; +} + +void ASTDumper::visitInlineCommandComment(const InlineCommandComment *C) { + OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; + switch (C->getRenderKind()) { + case InlineCommandComment::RenderNormal: + OS << " RenderNormal"; + break; + case InlineCommandComment::RenderBold: + OS << " RenderBold"; + break; + case InlineCommandComment::RenderMonospaced: + OS << " RenderMonospaced"; + break; + case InlineCommandComment::RenderEmphasized: + OS << " RenderEmphasized"; + break; + } + + for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) + OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; +} + +void ASTDumper::visitHTMLStartTagComment(const HTMLStartTagComment *C) { + OS << " Name=\"" << C->getTagName() << "\""; + if (C->getNumAttrs() != 0) { + OS << " Attrs: "; + for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) { + const HTMLStartTagComment::Attribute &Attr = C->getAttr(i); + OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\""; + } + } + if (C->isSelfClosing()) + OS << " SelfClosing"; +} + +void ASTDumper::visitHTMLEndTagComment(const HTMLEndTagComment *C) { + OS << " Name=\"" << C->getTagName() << "\""; +} + +void ASTDumper::visitBlockCommandComment(const BlockCommandComment *C) { + OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; + for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) + OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; +} + +void ASTDumper::visitParamCommandComment(const ParamCommandComment *C) { + OS << " " << ParamCommandComment::getDirectionAsString(C->getDirection()); + + if (C->isDirectionExplicit()) + OS << " explicitly"; + else + OS << " implicitly"; + + if (C->hasParamName()) { + if (C->isParamIndexValid()) + OS << " Param=\"" << C->getParamName(FC) << "\""; + else + OS << " Param=\"" << C->getParamNameAsWritten() << "\""; + } + + if (C->isParamIndexValid()) + OS << " ParamIndex=" << C->getParamIndex(); +} + +void ASTDumper::visitTParamCommandComment(const TParamCommandComment *C) { + if (C->hasParamName()) { + if (C->isPositionValid()) + OS << " Param=\"" << C->getParamName(FC) << "\""; + else + OS << " Param=\"" << C->getParamNameAsWritten() << "\""; + } + + if (C->isPositionValid()) { + OS << " Position=<"; + for (unsigned i = 0, e = C->getDepth(); i != e; ++i) { + OS << C->getIndex(i); + if (i != e - 1) + OS << ", "; + } + OS << ">"; + } +} + +void ASTDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) { + OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"" + " CloseName=\"" << C->getCloseName() << "\""; +} + +void ASTDumper::visitVerbatimBlockLineComment( + const VerbatimBlockLineComment *C) { + OS << " Text=\"" << C->getText() << "\""; +} + +void ASTDumper::visitVerbatimLineComment(const VerbatimLineComment *C) { + OS << " Text=\"" << C->getText() << "\""; +} + +//===----------------------------------------------------------------------===// +// Decl method implementations +//===----------------------------------------------------------------------===// + +void Decl::dump() const { + dump(llvm::errs()); +} + +void Decl::dump(raw_ostream &OS) const { + ASTDumper P(OS, &getASTContext().getCommentCommandTraits(), + &getASTContext().getSourceManager()); + P.dumpDecl(this); +} + +void Decl::dumpColor() const { + ASTDumper P(llvm::errs(), &getASTContext().getCommentCommandTraits(), + &getASTContext().getSourceManager(), /*ShowColors*/true); + P.dumpDecl(this); +} +//===----------------------------------------------------------------------===// +// Stmt method implementations +//===----------------------------------------------------------------------===// + +void Stmt::dump(SourceManager &SM) const { + dump(llvm::errs(), SM); +} + +void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { + ASTDumper P(OS, 0, &SM); + P.dumpStmt(this); +} + +void Stmt::dump() const { + ASTDumper P(llvm::errs(), 0, 0); + P.dumpStmt(this); +} + +void Stmt::dumpColor() const { + ASTDumper P(llvm::errs(), 0, 0, /*ShowColors*/true); + P.dumpStmt(this); +} + +//===----------------------------------------------------------------------===// +// Comment method implementations +//===----------------------------------------------------------------------===// + +void Comment::dump() const { + dump(llvm::errs(), 0, 0); +} + +void Comment::dump(const ASTContext &Context) const { + dump(llvm::errs(), &Context.getCommentCommandTraits(), + &Context.getSourceManager()); +} + +void Comment::dump(raw_ostream &OS, const CommandTraits *Traits, + const SourceManager *SM) const { + const FullComment *FC = dyn_cast<FullComment>(this); + ASTDumper D(OS, Traits, SM); + D.dumpFullComment(FC); +} + +void Comment::dumpColor() const { + const FullComment *FC = dyn_cast<FullComment>(this); + ASTDumper D(llvm::errs(), 0, 0, /*ShowColors*/true); + D.dumpFullComment(FC); +} |