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, bool DumpDeclTypes = false) 40 : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)), 41 OutputKind(K), OutputFormat(Format), FilterString(FilterString), 42 DumpLookups(DumpLookups), DumpDeclTypes(DumpDeclTypes) {} 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 if (DumpDeclTypes) { 99 Decl *InnerD = D; 100 if (auto *TD = dyn_cast<TemplateDecl>(D)) 101 InnerD = TD->getTemplatedDecl(); 102 103 // FIXME: Support OutputFormat in type dumping. 104 // FIXME: Support combining -ast-dump-decl-types with -ast-dump-lookups. 105 if (auto *VD = dyn_cast<ValueDecl>(InnerD)) 106 VD->getType().dump(Out, VD->getASTContext()); 107 if (auto *TD = dyn_cast<TypeDecl>(InnerD)) 108 TD->getTypeForDecl()->dump(Out, TD->getASTContext()); 109 } 110 } 111 112 raw_ostream &Out; 113 std::unique_ptr<raw_ostream> OwnedOut; 114 115 /// How to output individual declarations. 116 Kind OutputKind; 117 118 /// What format should the output take? 119 ASTDumpOutputFormat OutputFormat; 120 121 /// Which declarations or DeclContexts to display. 122 std::string FilterString; 123 124 /// Whether the primary output is lookup results or declarations. Individual 125 /// results will be output with a format determined by OutputKind. This is 126 /// incompatible with OutputKind == Print. 127 bool DumpLookups; 128 129 /// Whether to dump the type for each declaration dumped. 130 bool DumpDeclTypes; 131 }; 132 133 class ASTDeclNodeLister : public ASTConsumer, 134 public RecursiveASTVisitor<ASTDeclNodeLister> { 135 public: 136 ASTDeclNodeLister(raw_ostream *Out = nullptr) 137 : Out(Out ? *Out : llvm::outs()) {} 138 139 void HandleTranslationUnit(ASTContext &Context) override { 140 TraverseDecl(Context.getTranslationUnitDecl()); 141 } 142 143 bool shouldWalkTypesOfTypeLocs() const { return false; } 144 145 bool VisitNamedDecl(NamedDecl *D) { 146 D->printQualifiedName(Out); 147 Out << '\n'; 148 return true; 149 } 150 151 private: 152 raw_ostream &Out; 153 }; 154 } // end anonymous namespace 155 156 std::unique_ptr<ASTConsumer> 157 clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out, 158 StringRef FilterString) { 159 return std::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print, 160 ADOF_Default, FilterString); 161 } 162 163 std::unique_ptr<ASTConsumer> 164 clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, StringRef FilterString, 165 bool DumpDecls, bool Deserialize, bool DumpLookups, 166 bool DumpDeclTypes, ASTDumpOutputFormat Format) { 167 assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump"); 168 return std::make_unique<ASTPrinter>( 169 std::move(Out), 170 Deserialize ? ASTPrinter::DumpFull 171 : DumpDecls ? ASTPrinter::Dump : ASTPrinter::None, 172 Format, FilterString, DumpLookups, DumpDeclTypes); 173 } 174 175 std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() { 176 return std::make_unique<ASTDeclNodeLister>(nullptr); 177 } 178 179 //===----------------------------------------------------------------------===// 180 /// ASTViewer - AST Visualization 181 182 namespace { 183 class ASTViewer : public ASTConsumer { 184 ASTContext *Context; 185 public: 186 void Initialize(ASTContext &Context) override { 187 this->Context = &Context; 188 } 189 190 bool HandleTopLevelDecl(DeclGroupRef D) override { 191 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) 192 HandleTopLevelSingleDecl(*I); 193 return true; 194 } 195 196 void HandleTopLevelSingleDecl(Decl *D); 197 }; 198 } 199 200 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { 201 if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { 202 D->print(llvm::errs()); 203 204 if (Stmt *Body = D->getBody()) { 205 llvm::errs() << '\n'; 206 Body->viewAST(); 207 llvm::errs() << '\n'; 208 } 209 } 210 } 211 212 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() { 213 return std::make_unique<ASTViewer>(); 214 } 215