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