clang API Documentation
00001 //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // AST Consumer Implementations. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/Frontend/ASTConsumers.h" 00015 #include "clang/AST/AST.h" 00016 #include "clang/AST/ASTConsumer.h" 00017 #include "clang/AST/ASTContext.h" 00018 #include "clang/AST/PrettyPrinter.h" 00019 #include "clang/AST/RecordLayout.h" 00020 #include "clang/AST/RecursiveASTVisitor.h" 00021 #include "clang/Basic/Diagnostic.h" 00022 #include "clang/Basic/FileManager.h" 00023 #include "clang/Basic/SourceManager.h" 00024 #include "llvm/IR/Module.h" 00025 #include "llvm/Support/Path.h" 00026 #include "llvm/Support/Timer.h" 00027 #include "llvm/Support/raw_ostream.h" 00028 using namespace clang; 00029 00030 //===----------------------------------------------------------------------===// 00031 /// ASTPrinter - Pretty-printer and dumper of ASTs 00032 00033 namespace { 00034 class ASTPrinter : public ASTConsumer, 00035 public RecursiveASTVisitor<ASTPrinter> { 00036 typedef RecursiveASTVisitor<ASTPrinter> base; 00037 00038 public: 00039 ASTPrinter(raw_ostream *Out = nullptr, bool Dump = false, 00040 StringRef FilterString = "", bool DumpLookups = false) 00041 : Out(Out ? *Out : llvm::outs()), Dump(Dump), 00042 FilterString(FilterString), DumpLookups(DumpLookups) {} 00043 00044 void HandleTranslationUnit(ASTContext &Context) override { 00045 TranslationUnitDecl *D = Context.getTranslationUnitDecl(); 00046 00047 if (FilterString.empty()) 00048 return print(D); 00049 00050 TraverseDecl(D); 00051 } 00052 00053 bool shouldWalkTypesOfTypeLocs() const { return false; } 00054 00055 bool TraverseDecl(Decl *D) { 00056 if (D && filterMatches(D)) { 00057 bool ShowColors = Out.has_colors(); 00058 if (ShowColors) 00059 Out.changeColor(raw_ostream::BLUE); 00060 Out << ((Dump || DumpLookups) ? "Dumping " : "Printing ") << getName(D) 00061 << ":\n"; 00062 if (ShowColors) 00063 Out.resetColor(); 00064 print(D); 00065 Out << "\n"; 00066 // Don't traverse child nodes to avoid output duplication. 00067 return true; 00068 } 00069 return base::TraverseDecl(D); 00070 } 00071 00072 private: 00073 std::string getName(Decl *D) { 00074 if (isa<NamedDecl>(D)) 00075 return cast<NamedDecl>(D)->getQualifiedNameAsString(); 00076 return ""; 00077 } 00078 bool filterMatches(Decl *D) { 00079 return getName(D).find(FilterString) != std::string::npos; 00080 } 00081 void print(Decl *D) { 00082 if (DumpLookups) { 00083 if (DeclContext *DC = dyn_cast<DeclContext>(D)) { 00084 if (DC == DC->getPrimaryContext()) 00085 DC->dumpLookups(Out, Dump); 00086 else 00087 Out << "Lookup map is in primary DeclContext " 00088 << DC->getPrimaryContext() << "\n"; 00089 } else 00090 Out << "Not a DeclContext\n"; 00091 } else if (Dump) 00092 D->dump(Out); 00093 else 00094 D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true); 00095 } 00096 00097 raw_ostream &Out; 00098 bool Dump; 00099 std::string FilterString; 00100 bool DumpLookups; 00101 }; 00102 00103 class ASTDeclNodeLister : public ASTConsumer, 00104 public RecursiveASTVisitor<ASTDeclNodeLister> { 00105 public: 00106 ASTDeclNodeLister(raw_ostream *Out = nullptr) 00107 : Out(Out ? *Out : llvm::outs()) {} 00108 00109 void HandleTranslationUnit(ASTContext &Context) override { 00110 TraverseDecl(Context.getTranslationUnitDecl()); 00111 } 00112 00113 bool shouldWalkTypesOfTypeLocs() const { return false; } 00114 00115 bool VisitNamedDecl(NamedDecl *D) { 00116 D->printQualifiedName(Out); 00117 Out << '\n'; 00118 return true; 00119 } 00120 00121 private: 00122 raw_ostream &Out; 00123 }; 00124 } // end anonymous namespace 00125 00126 std::unique_ptr<ASTConsumer> clang::CreateASTPrinter(raw_ostream *Out, 00127 StringRef FilterString) { 00128 return llvm::make_unique<ASTPrinter>(Out, /*Dump=*/false, FilterString); 00129 } 00130 00131 std::unique_ptr<ASTConsumer> clang::CreateASTDumper(StringRef FilterString, 00132 bool DumpDecls, 00133 bool DumpLookups) { 00134 assert((DumpDecls || DumpLookups) && "nothing to dump"); 00135 return llvm::make_unique<ASTPrinter>(nullptr, DumpDecls, FilterString, 00136 DumpLookups); 00137 } 00138 00139 std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() { 00140 return llvm::make_unique<ASTDeclNodeLister>(nullptr); 00141 } 00142 00143 //===----------------------------------------------------------------------===// 00144 /// ASTViewer - AST Visualization 00145 00146 namespace { 00147 class ASTViewer : public ASTConsumer { 00148 ASTContext *Context; 00149 public: 00150 void Initialize(ASTContext &Context) override { 00151 this->Context = &Context; 00152 } 00153 00154 bool HandleTopLevelDecl(DeclGroupRef D) override { 00155 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) 00156 HandleTopLevelSingleDecl(*I); 00157 return true; 00158 } 00159 00160 void HandleTopLevelSingleDecl(Decl *D); 00161 }; 00162 } 00163 00164 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { 00165 if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { 00166 D->print(llvm::errs()); 00167 00168 if (Stmt *Body = D->getBody()) { 00169 llvm::errs() << '\n'; 00170 Body->viewAST(); 00171 llvm::errs() << '\n'; 00172 } 00173 } 00174 } 00175 00176 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() { 00177 return llvm::make_unique<ASTViewer>(); 00178 } 00179 00180 //===----------------------------------------------------------------------===// 00181 /// DeclContextPrinter - Decl and DeclContext Visualization 00182 00183 namespace { 00184 00185 class DeclContextPrinter : public ASTConsumer { 00186 raw_ostream& Out; 00187 public: 00188 DeclContextPrinter() : Out(llvm::errs()) {} 00189 00190 void HandleTranslationUnit(ASTContext &C) override { 00191 PrintDeclContext(C.getTranslationUnitDecl(), 4); 00192 } 00193 00194 void PrintDeclContext(const DeclContext* DC, unsigned Indentation); 00195 }; 00196 } // end anonymous namespace 00197 00198 void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, 00199 unsigned Indentation) { 00200 // Print DeclContext name. 00201 switch (DC->getDeclKind()) { 00202 case Decl::TranslationUnit: 00203 Out << "[translation unit] " << DC; 00204 break; 00205 case Decl::Namespace: { 00206 Out << "[namespace] "; 00207 const NamespaceDecl* ND = cast<NamespaceDecl>(DC); 00208 Out << *ND; 00209 break; 00210 } 00211 case Decl::Enum: { 00212 const EnumDecl* ED = cast<EnumDecl>(DC); 00213 if (ED->isCompleteDefinition()) 00214 Out << "[enum] "; 00215 else 00216 Out << "<enum> "; 00217 Out << *ED; 00218 break; 00219 } 00220 case Decl::Record: { 00221 const RecordDecl* RD = cast<RecordDecl>(DC); 00222 if (RD->isCompleteDefinition()) 00223 Out << "[struct] "; 00224 else 00225 Out << "<struct> "; 00226 Out << *RD; 00227 break; 00228 } 00229 case Decl::CXXRecord: { 00230 const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC); 00231 if (RD->isCompleteDefinition()) 00232 Out << "[class] "; 00233 else 00234 Out << "<class> "; 00235 Out << *RD << ' ' << DC; 00236 break; 00237 } 00238 case Decl::ObjCMethod: 00239 Out << "[objc method]"; 00240 break; 00241 case Decl::ObjCInterface: 00242 Out << "[objc interface]"; 00243 break; 00244 case Decl::ObjCCategory: 00245 Out << "[objc category]"; 00246 break; 00247 case Decl::ObjCProtocol: 00248 Out << "[objc protocol]"; 00249 break; 00250 case Decl::ObjCImplementation: 00251 Out << "[objc implementation]"; 00252 break; 00253 case Decl::ObjCCategoryImpl: 00254 Out << "[objc categoryimpl]"; 00255 break; 00256 case Decl::LinkageSpec: 00257 Out << "[linkage spec]"; 00258 break; 00259 case Decl::Block: 00260 Out << "[block]"; 00261 break; 00262 case Decl::Function: { 00263 const FunctionDecl* FD = cast<FunctionDecl>(DC); 00264 if (FD->doesThisDeclarationHaveABody()) 00265 Out << "[function] "; 00266 else 00267 Out << "<function> "; 00268 Out << *FD; 00269 // Print the parameters. 00270 Out << "("; 00271 bool PrintComma = false; 00272 for (auto I : FD->params()) { 00273 if (PrintComma) 00274 Out << ", "; 00275 else 00276 PrintComma = true; 00277 Out << *I; 00278 } 00279 Out << ")"; 00280 break; 00281 } 00282 case Decl::CXXMethod: { 00283 const CXXMethodDecl* D = cast<CXXMethodDecl>(DC); 00284 if (D->isOutOfLine()) 00285 Out << "[c++ method] "; 00286 else if (D->isImplicit()) 00287 Out << "(c++ method) "; 00288 else 00289 Out << "<c++ method> "; 00290 Out << *D; 00291 // Print the parameters. 00292 Out << "("; 00293 bool PrintComma = false; 00294 for (FunctionDecl::param_const_iterator I = D->param_begin(), 00295 E = D->param_end(); I != E; ++I) { 00296 if (PrintComma) 00297 Out << ", "; 00298 else 00299 PrintComma = true; 00300 Out << **I; 00301 } 00302 Out << ")"; 00303 00304 // Check the semantic DeclContext. 00305 const DeclContext* SemaDC = D->getDeclContext(); 00306 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 00307 if (SemaDC != LexicalDC) 00308 Out << " [[" << SemaDC << "]]"; 00309 00310 break; 00311 } 00312 case Decl::CXXConstructor: { 00313 const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC); 00314 if (D->isOutOfLine()) 00315 Out << "[c++ ctor] "; 00316 else if (D->isImplicit()) 00317 Out << "(c++ ctor) "; 00318 else 00319 Out << "<c++ ctor> "; 00320 Out << *D; 00321 // Print the parameters. 00322 Out << "("; 00323 bool PrintComma = false; 00324 for (FunctionDecl::param_const_iterator I = D->param_begin(), 00325 E = D->param_end(); I != E; ++I) { 00326 if (PrintComma) 00327 Out << ", "; 00328 else 00329 PrintComma = true; 00330 Out << **I; 00331 } 00332 Out << ")"; 00333 00334 // Check the semantic DC. 00335 const DeclContext* SemaDC = D->getDeclContext(); 00336 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 00337 if (SemaDC != LexicalDC) 00338 Out << " [[" << SemaDC << "]]"; 00339 break; 00340 } 00341 case Decl::CXXDestructor: { 00342 const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC); 00343 if (D->isOutOfLine()) 00344 Out << "[c++ dtor] "; 00345 else if (D->isImplicit()) 00346 Out << "(c++ dtor) "; 00347 else 00348 Out << "<c++ dtor> "; 00349 Out << *D; 00350 // Check the semantic DC. 00351 const DeclContext* SemaDC = D->getDeclContext(); 00352 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 00353 if (SemaDC != LexicalDC) 00354 Out << " [[" << SemaDC << "]]"; 00355 break; 00356 } 00357 case Decl::CXXConversion: { 00358 const CXXConversionDecl* D = cast<CXXConversionDecl>(DC); 00359 if (D->isOutOfLine()) 00360 Out << "[c++ conversion] "; 00361 else if (D->isImplicit()) 00362 Out << "(c++ conversion) "; 00363 else 00364 Out << "<c++ conversion> "; 00365 Out << *D; 00366 // Check the semantic DC. 00367 const DeclContext* SemaDC = D->getDeclContext(); 00368 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 00369 if (SemaDC != LexicalDC) 00370 Out << " [[" << SemaDC << "]]"; 00371 break; 00372 } 00373 00374 default: 00375 llvm_unreachable("a decl that inherits DeclContext isn't handled"); 00376 } 00377 00378 Out << "\n"; 00379 00380 // Print decls in the DeclContext. 00381 for (auto *I : DC->decls()) { 00382 for (unsigned i = 0; i < Indentation; ++i) 00383 Out << " "; 00384 00385 Decl::Kind DK = I->getKind(); 00386 switch (DK) { 00387 case Decl::Namespace: 00388 case Decl::Enum: 00389 case Decl::Record: 00390 case Decl::CXXRecord: 00391 case Decl::ObjCMethod: 00392 case Decl::ObjCInterface: 00393 case Decl::ObjCCategory: 00394 case Decl::ObjCProtocol: 00395 case Decl::ObjCImplementation: 00396 case Decl::ObjCCategoryImpl: 00397 case Decl::LinkageSpec: 00398 case Decl::Block: 00399 case Decl::Function: 00400 case Decl::CXXMethod: 00401 case Decl::CXXConstructor: 00402 case Decl::CXXDestructor: 00403 case Decl::CXXConversion: 00404 { 00405 DeclContext* DC = cast<DeclContext>(I); 00406 PrintDeclContext(DC, Indentation+2); 00407 break; 00408 } 00409 case Decl::IndirectField: { 00410 IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(I); 00411 Out << "<IndirectField> " << *IFD << '\n'; 00412 break; 00413 } 00414 case Decl::Label: { 00415 LabelDecl *LD = cast<LabelDecl>(I); 00416 Out << "<Label> " << *LD << '\n'; 00417 break; 00418 } 00419 case Decl::Field: { 00420 FieldDecl *FD = cast<FieldDecl>(I); 00421 Out << "<field> " << *FD << '\n'; 00422 break; 00423 } 00424 case Decl::Typedef: 00425 case Decl::TypeAlias: { 00426 TypedefNameDecl* TD = cast<TypedefNameDecl>(I); 00427 Out << "<typedef> " << *TD << '\n'; 00428 break; 00429 } 00430 case Decl::EnumConstant: { 00431 EnumConstantDecl* ECD = cast<EnumConstantDecl>(I); 00432 Out << "<enum constant> " << *ECD << '\n'; 00433 break; 00434 } 00435 case Decl::Var: { 00436 VarDecl* VD = cast<VarDecl>(I); 00437 Out << "<var> " << *VD << '\n'; 00438 break; 00439 } 00440 case Decl::ImplicitParam: { 00441 ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(I); 00442 Out << "<implicit parameter> " << *IPD << '\n'; 00443 break; 00444 } 00445 case Decl::ParmVar: { 00446 ParmVarDecl* PVD = cast<ParmVarDecl>(I); 00447 Out << "<parameter> " << *PVD << '\n'; 00448 break; 00449 } 00450 case Decl::ObjCProperty: { 00451 ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(I); 00452 Out << "<objc property> " << *OPD << '\n'; 00453 break; 00454 } 00455 case Decl::FunctionTemplate: { 00456 FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(I); 00457 Out << "<function template> " << *FTD << '\n'; 00458 break; 00459 } 00460 case Decl::FileScopeAsm: { 00461 Out << "<file-scope asm>\n"; 00462 break; 00463 } 00464 case Decl::UsingDirective: { 00465 Out << "<using directive>\n"; 00466 break; 00467 } 00468 case Decl::NamespaceAlias: { 00469 NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(I); 00470 Out << "<namespace alias> " << *NAD << '\n'; 00471 break; 00472 } 00473 case Decl::ClassTemplate: { 00474 ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(I); 00475 Out << "<class template> " << *CTD << '\n'; 00476 break; 00477 } 00478 case Decl::OMPThreadPrivate: { 00479 Out << "<omp threadprivate> " << '"' << I << "\"\n"; 00480 break; 00481 } 00482 default: 00483 Out << "DeclKind: " << DK << '"' << I << "\"\n"; 00484 llvm_unreachable("decl unhandled"); 00485 } 00486 } 00487 } 00488 std::unique_ptr<ASTConsumer> clang::CreateDeclContextPrinter() { 00489 return llvm::make_unique<DeclContextPrinter>(); 00490 }