ASTConsumers.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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)
  36. : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)),
  37. OutputKind(K), OutputFormat(Format), FilterString(FilterString),
  38. DumpLookups(DumpLookups) {}
  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. Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D)
  52. << ":\n";
  53. if (ShowColors)
  54. Out.resetColor();
  55. print(D);
  56. Out << "\n";
  57. // Don't traverse child nodes to avoid output duplication.
  58. return true;
  59. }
  60. return base::TraverseDecl(D);
  61. }
  62. private:
  63. std::string getName(Decl *D) {
  64. if (isa<NamedDecl>(D))
  65. return cast<NamedDecl>(D)->getQualifiedNameAsString();
  66. return "";
  67. }
  68. bool filterMatches(Decl *D) {
  69. return getName(D).find(FilterString) != std::string::npos;
  70. }
  71. void print(Decl *D) {
  72. if (DumpLookups) {
  73. if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
  74. if (DC == DC->getPrimaryContext())
  75. DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull);
  76. else
  77. Out << "Lookup map is in primary DeclContext "
  78. << DC->getPrimaryContext() << "\n";
  79. } else
  80. Out << "Not a DeclContext\n";
  81. } else if (OutputKind == Print) {
  82. PrintingPolicy Policy(D->getASTContext().getLangOpts());
  83. D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
  84. } else if (OutputKind != None)
  85. D->dump(Out, OutputKind == DumpFull, OutputFormat);
  86. }
  87. raw_ostream &Out;
  88. std::unique_ptr<raw_ostream> OwnedOut;
  89. /// How to output individual declarations.
  90. Kind OutputKind;
  91. /// What format should the output take?
  92. ASTDumpOutputFormat OutputFormat;
  93. /// Which declarations or DeclContexts to display.
  94. std::string FilterString;
  95. /// Whether the primary output is lookup results or declarations. Individual
  96. /// results will be output with a format determined by OutputKind. This is
  97. /// incompatible with OutputKind == Print.
  98. bool DumpLookups;
  99. };
  100. class ASTDeclNodeLister : public ASTConsumer,
  101. public RecursiveASTVisitor<ASTDeclNodeLister> {
  102. public:
  103. ASTDeclNodeLister(raw_ostream *Out = nullptr)
  104. : Out(Out ? *Out : llvm::outs()) {}
  105. void HandleTranslationUnit(ASTContext &Context) override {
  106. TraverseDecl(Context.getTranslationUnitDecl());
  107. }
  108. bool shouldWalkTypesOfTypeLocs() const { return false; }
  109. bool VisitNamedDecl(NamedDecl *D) {
  110. D->printQualifiedName(Out);
  111. Out << '\n';
  112. return true;
  113. }
  114. private:
  115. raw_ostream &Out;
  116. };
  117. } // end anonymous namespace
  118. std::unique_ptr<ASTConsumer>
  119. clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out,
  120. StringRef FilterString) {
  121. return std::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print,
  122. ADOF_Default, FilterString);
  123. }
  124. std::unique_ptr<ASTConsumer>
  125. clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, StringRef FilterString,
  126. bool DumpDecls, bool Deserialize, bool DumpLookups,
  127. ASTDumpOutputFormat Format) {
  128. assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump");
  129. return std::make_unique<ASTPrinter>(std::move(Out),
  130. Deserialize ? ASTPrinter::DumpFull :
  131. DumpDecls ? ASTPrinter::Dump :
  132. ASTPrinter::None, Format,
  133. FilterString, DumpLookups);
  134. }
  135. std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
  136. return std::make_unique<ASTDeclNodeLister>(nullptr);
  137. }
  138. //===----------------------------------------------------------------------===//
  139. /// ASTViewer - AST Visualization
  140. namespace {
  141. class ASTViewer : public ASTConsumer {
  142. ASTContext *Context;
  143. public:
  144. void Initialize(ASTContext &Context) override {
  145. this->Context = &Context;
  146. }
  147. bool HandleTopLevelDecl(DeclGroupRef D) override {
  148. for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
  149. HandleTopLevelSingleDecl(*I);
  150. return true;
  151. }
  152. void HandleTopLevelSingleDecl(Decl *D);
  153. };
  154. }
  155. void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
  156. if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
  157. D->print(llvm::errs());
  158. if (Stmt *Body = D->getBody()) {
  159. llvm::errs() << '\n';
  160. Body->viewAST();
  161. llvm::errs() << '\n';
  162. }
  163. }
  164. }
  165. std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
  166. return std::make_unique<ASTViewer>();
  167. }