ASTConsumers.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
  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. // AST Consumer Implementations.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "clang/Frontend/ASTConsumers.h"
  13. #include "clang/AST/AST.h"
  14. #include "clang/AST/ASTConsumer.h"
  15. #include "clang/AST/ASTContext.h"
  16. #include "clang/AST/PrettyPrinter.h"
  17. #include "clang/AST/RecordLayout.h"
  18. #include "clang/AST/RecursiveASTVisitor.h"
  19. #include "clang/Basic/Diagnostic.h"
  20. #include "clang/Basic/SourceManager.h"
  21. #include "llvm/Support/Path.h"
  22. #include "llvm/Support/Timer.h"
  23. #include "llvm/Support/raw_ostream.h"
  24. using namespace clang;
  25. //===----------------------------------------------------------------------===//
  26. /// ASTPrinter - Pretty-printer and dumper of ASTs
  27. namespace {
  28. class ASTPrinter : public ASTConsumer,
  29. public RecursiveASTVisitor<ASTPrinter> {
  30. typedef RecursiveASTVisitor<ASTPrinter> base;
  31. public:
  32. enum Kind { DumpFull, Dump, Print, None };
  33. ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K,
  34. ASTDumpOutputFormat Format, StringRef FilterString,
  35. bool DumpLookups = false, bool DumpDeclTypes = false)
  36. : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
  37. OutputKind(K), OutputFormat(Format), FilterString(FilterString),
  38. DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {}
  39. void HandleTranslationUnit(ASTContext &Context) override {
  40. TranslationUnitDecl *D = Context.getTranslationUnitDecl();
  41. if (FilterString.empty())
  42. return print(D);
  43. TraverseDecl(D);
  44. }
  45. bool shouldWalkTypesOfTypeLocs() const { return false; }
  46. bool TraverseDecl(Decl *D) {
  47. if (D && filterMatches(D)) {
  48. bool ShowColors = Out.has_colors();
  49. if (ShowColors)
  50. Out.changeColor(raw_ostream::BLUE);
  51. if (OutputFormat == ADOF_Default)
  52. Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D)
  53. << ":\n";
  54. if (ShowColors)
  55. Out.resetColor();
  56. print(D);
  57. Out << "\n";
  58. // Don't traverse child nodes to avoid output duplication.
  59. return true;
  60. }
  61. return base::TraverseDecl(D);
  62. }
  63. private:
  64. std::string getName(Decl *D) {
  65. if (isa<NamedDecl>(D))
  66. return cast<NamedDecl>(D)->getQualifiedNameAsString();
  67. return "";
  68. }
  69. bool filterMatches(Decl *D) {
  70. return getName(D).find(FilterString) != std::string::npos;
  71. }
  72. void print(Decl *D) {
  73. if (DumpLookups) {
  74. if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
  75. if (DC == DC->getPrimaryContext())
  76. DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull);
  77. else
  78. Out << "Lookup map is in primary DeclContext "
  79. << DC->getPrimaryContext() << "\n";
  80. } else
  81. Out << "Not a DeclContext\n";
  82. } else if (OutputKind == Print) {
  83. PrintingPolicy Policy(D->getASTContext().getLangOpts());
  84. D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
  85. } else if (OutputKind != None) {
  86. D->dump(Out, OutputKind == DumpFull, OutputFormat);
  87. }
  88. if (DumpDeclTypes) {
  89. Decl *InnerD = D;
  90. if (auto *TD = dyn_cast<TemplateDecl>(D))
  91. InnerD = TD->getTemplatedDecl();
  92. // FIXME: Support OutputFormat in type dumping.
  93. // FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups.
  94. if (auto *VD = dyn_cast<ValueDecl>(InnerD))
  95. VD->getType().dump(Out, VD->getASTContext());
  96. if (auto *TD = dyn_cast<TypeDecl>(InnerD))
  97. TD->getTypeForDecl()->dump(Out, TD->getASTContext());
  98. }
  99. }
  100. raw_ostream &Out;
  101. std::unique_ptr<raw_ostream> OwnedOut;
  102. /// How to output individual declarations.
  103. Kind OutputKind;
  104. /// What format should the output take?
  105. ASTDumpOutputFormat OutputFormat;
  106. /// Which declarations or DeclContexts to display.
  107. std::string FilterString;
  108. /// Whether the primary output is lookup results or declarations. Individual
  109. /// results will be output with a format determined by OutputKind. This is
  110. /// incompatible with OutputKind == Print.
  111. bool DumpLookups;
  112. /// Whether to dump the type for each declaration dumped.
  113. bool DumpDeclTypes;
  114. };
  115. class ASTDeclNodeLister : public ASTConsumer,
  116. public RecursiveASTVisitor<ASTDeclNodeLister> {
  117. public:
  118. ASTDeclNodeLister(raw_ostream *Out = nullptr)
  119. : Out(Out ? *Out : llvm::outs()) {}
  120. void HandleTranslationUnit(ASTContext &Context) override {
  121. TraverseDecl(Context.getTranslationUnitDecl());
  122. }
  123. bool shouldWalkTypesOfTypeLocs() const { return false; }
  124. bool VisitNamedDecl(NamedDecl *D) {
  125. D->printQualifiedName(Out);
  126. Out << '\n';
  127. return true;
  128. }
  129. private:
  130. raw_ostream &Out;
  131. };
  132. } // end anonymous namespace
  133. std::unique_ptr<ASTConsumer>
  134. clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
  135. StringRef FilterString) {
  136. return std::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
  137. ADOF_Default, FilterString);
  138. }
  139. std::unique_ptr<ASTConsumer>
  140. clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, StringRef FilterString,
  141. bool DumpDecls, bool Deserialize, bool DumpLookups,
  142. bool DumpDeclTypes, ASTDumpOutputFormat Format) {
  143. assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
  144. return std::make_unique<ASTPrinter>(
  145. std::move(Out),
  146. Deserialize ? ASTPrinter::DumpFull
  147. : DumpDecls ? ASTPrinter::Dump : ASTPrinter::None,
  148. Format, FilterString, DumpLookups, DumpDeclTypes);
  149. }
  150. std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
  151. return std::make_unique<ASTDeclNodeLister>(nullptr);
  152. }
  153. //===----------------------------------------------------------------------===//
  154. /// ASTViewer - AST Visualization
  155. namespace {
  156. class ASTViewer : public ASTConsumer {
  157. ASTContext *Context;
  158. public:
  159. void Initialize(ASTContext &Context) override {
  160. this->Context = &Context;
  161. }
  162. bool HandleTopLevelDecl(DeclGroupRef D) override {
  163. for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
  164. HandleTopLevelSingleDecl(*I);
  165. return true;
  166. }
  167. void HandleTopLevelSingleDecl(Decl *D);
  168. };
  169. }
  170. void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
  171. if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
  172. D->print(llvm::errs());
  173. if (Stmt *Body = D->getBody()) {
  174. llvm::errs() << '\n';
  175. Body->viewAST();
  176. llvm::errs() << '\n';
  177. }
  178. }
  179. }
  180. std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
  181. return std::make_unique<ASTViewer>();
  182. }