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