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