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/Basic/Diagnostic.h" 00016 #include "clang/Basic/SourceManager.h" 00017 #include "clang/Basic/FileManager.h" 00018 #include "clang/AST/AST.h" 00019 #include "clang/AST/ASTConsumer.h" 00020 #include "clang/AST/ASTContext.h" 00021 #include "clang/AST/RecordLayout.h" 00022 #include "clang/AST/PrettyPrinter.h" 00023 #include "llvm/Module.h" 00024 #include "llvm/Support/Timer.h" 00025 #include "llvm/Support/raw_ostream.h" 00026 #include "llvm/Support/Path.h" 00027 using namespace clang; 00028 00029 //===----------------------------------------------------------------------===// 00030 /// ASTPrinter - Pretty-printer and dumper of ASTs 00031 00032 namespace { 00033 class ASTPrinter : public ASTConsumer { 00034 raw_ostream &Out; 00035 bool Dump; 00036 00037 public: 00038 ASTPrinter(raw_ostream* o = NULL, bool Dump = false) 00039 : Out(o? *o : llvm::outs()), Dump(Dump) { } 00040 00041 virtual void HandleTranslationUnit(ASTContext &Context) { 00042 PrintingPolicy Policy = Context.getPrintingPolicy(); 00043 Policy.Dump = Dump; 00044 Context.getTranslationUnitDecl()->print(Out, Policy, /*Indentation=*/0, 00045 /*PrintInstantiation=*/true); 00046 } 00047 }; 00048 } // end anonymous namespace 00049 00050 ASTConsumer *clang::CreateASTPrinter(raw_ostream* out) { 00051 return new ASTPrinter(out); 00052 } 00053 00054 ASTConsumer *clang::CreateASTDumper() { 00055 return new ASTPrinter(0, true); 00056 } 00057 00058 //===----------------------------------------------------------------------===// 00059 /// ASTViewer - AST Visualization 00060 00061 namespace { 00062 class ASTViewer : public ASTConsumer { 00063 ASTContext *Context; 00064 public: 00065 void Initialize(ASTContext &Context) { 00066 this->Context = &Context; 00067 } 00068 00069 virtual bool HandleTopLevelDecl(DeclGroupRef D) { 00070 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) 00071 HandleTopLevelSingleDecl(*I); 00072 return true; 00073 } 00074 00075 void HandleTopLevelSingleDecl(Decl *D); 00076 }; 00077 } 00078 00079 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { 00080 if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { 00081 D->print(llvm::errs()); 00082 00083 if (Stmt *Body = D->getBody()) { 00084 llvm::errs() << '\n'; 00085 Body->viewAST(); 00086 llvm::errs() << '\n'; 00087 } 00088 } 00089 } 00090 00091 00092 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); } 00093 00094 //===----------------------------------------------------------------------===// 00095 /// DeclContextPrinter - Decl and DeclContext Visualization 00096 00097 namespace { 00098 00099 class DeclContextPrinter : public ASTConsumer { 00100 raw_ostream& Out; 00101 public: 00102 DeclContextPrinter() : Out(llvm::errs()) {} 00103 00104 void HandleTranslationUnit(ASTContext &C) { 00105 PrintDeclContext(C.getTranslationUnitDecl(), 4); 00106 } 00107 00108 void PrintDeclContext(const DeclContext* DC, unsigned Indentation); 00109 }; 00110 } // end anonymous namespace 00111 00112 void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, 00113 unsigned Indentation) { 00114 // Print DeclContext name. 00115 switch (DC->getDeclKind()) { 00116 case Decl::TranslationUnit: 00117 Out << "[translation unit] " << DC; 00118 break; 00119 case Decl::Namespace: { 00120 Out << "[namespace] "; 00121 const NamespaceDecl* ND = cast<NamespaceDecl>(DC); 00122 Out << *ND; 00123 break; 00124 } 00125 case Decl::Enum: { 00126 const EnumDecl* ED = cast<EnumDecl>(DC); 00127 if (ED->isCompleteDefinition()) 00128 Out << "[enum] "; 00129 else 00130 Out << "<enum> "; 00131 Out << *ED; 00132 break; 00133 } 00134 case Decl::Record: { 00135 const RecordDecl* RD = cast<RecordDecl>(DC); 00136 if (RD->isCompleteDefinition()) 00137 Out << "[struct] "; 00138 else 00139 Out << "<struct> "; 00140 Out << *RD; 00141 break; 00142 } 00143 case Decl::CXXRecord: { 00144 const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC); 00145 if (RD->isCompleteDefinition()) 00146 Out << "[class] "; 00147 else 00148 Out << "<class> "; 00149 Out << *RD << ' ' << DC; 00150 break; 00151 } 00152 case Decl::ObjCMethod: 00153 Out << "[objc method]"; 00154 break; 00155 case Decl::ObjCInterface: 00156 Out << "[objc interface]"; 00157 break; 00158 case Decl::ObjCCategory: 00159 Out << "[objc category]"; 00160 break; 00161 case Decl::ObjCProtocol: 00162 Out << "[objc protocol]"; 00163 break; 00164 case Decl::ObjCImplementation: 00165 Out << "[objc implementation]"; 00166 break; 00167 case Decl::ObjCCategoryImpl: 00168 Out << "[objc categoryimpl]"; 00169 break; 00170 case Decl::LinkageSpec: 00171 Out << "[linkage spec]"; 00172 break; 00173 case Decl::Block: 00174 Out << "[block]"; 00175 break; 00176 case Decl::Function: { 00177 const FunctionDecl* FD = cast<FunctionDecl>(DC); 00178 if (FD->doesThisDeclarationHaveABody()) 00179 Out << "[function] "; 00180 else 00181 Out << "<function> "; 00182 Out << *FD; 00183 // Print the parameters. 00184 Out << "("; 00185 bool PrintComma = false; 00186 for (FunctionDecl::param_const_iterator I = FD->param_begin(), 00187 E = FD->param_end(); I != E; ++I) { 00188 if (PrintComma) 00189 Out << ", "; 00190 else 00191 PrintComma = true; 00192 Out << **I; 00193 } 00194 Out << ")"; 00195 break; 00196 } 00197 case Decl::CXXMethod: { 00198 const CXXMethodDecl* D = cast<CXXMethodDecl>(DC); 00199 if (D->isOutOfLine()) 00200 Out << "[c++ method] "; 00201 else if (D->isImplicit()) 00202 Out << "(c++ method) "; 00203 else 00204 Out << "<c++ method> "; 00205 Out << *D; 00206 // Print the parameters. 00207 Out << "("; 00208 bool PrintComma = false; 00209 for (FunctionDecl::param_const_iterator I = D->param_begin(), 00210 E = D->param_end(); I != E; ++I) { 00211 if (PrintComma) 00212 Out << ", "; 00213 else 00214 PrintComma = true; 00215 Out << **I; 00216 } 00217 Out << ")"; 00218 00219 // Check the semantic DeclContext. 00220 const DeclContext* SemaDC = D->getDeclContext(); 00221 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 00222 if (SemaDC != LexicalDC) 00223 Out << " [[" << SemaDC << "]]"; 00224 00225 break; 00226 } 00227 case Decl::CXXConstructor: { 00228 const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC); 00229 if (D->isOutOfLine()) 00230 Out << "[c++ ctor] "; 00231 else if (D->isImplicit()) 00232 Out << "(c++ ctor) "; 00233 else 00234 Out << "<c++ ctor> "; 00235 Out << *D; 00236 // Print the parameters. 00237 Out << "("; 00238 bool PrintComma = false; 00239 for (FunctionDecl::param_const_iterator I = D->param_begin(), 00240 E = D->param_end(); I != E; ++I) { 00241 if (PrintComma) 00242 Out << ", "; 00243 else 00244 PrintComma = true; 00245 Out << **I; 00246 } 00247 Out << ")"; 00248 00249 // Check the semantic DC. 00250 const DeclContext* SemaDC = D->getDeclContext(); 00251 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 00252 if (SemaDC != LexicalDC) 00253 Out << " [[" << SemaDC << "]]"; 00254 break; 00255 } 00256 case Decl::CXXDestructor: { 00257 const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC); 00258 if (D->isOutOfLine()) 00259 Out << "[c++ dtor] "; 00260 else if (D->isImplicit()) 00261 Out << "(c++ dtor) "; 00262 else 00263 Out << "<c++ dtor> "; 00264 Out << *D; 00265 // Check the semantic DC. 00266 const DeclContext* SemaDC = D->getDeclContext(); 00267 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 00268 if (SemaDC != LexicalDC) 00269 Out << " [[" << SemaDC << "]]"; 00270 break; 00271 } 00272 case Decl::CXXConversion: { 00273 const CXXConversionDecl* D = cast<CXXConversionDecl>(DC); 00274 if (D->isOutOfLine()) 00275 Out << "[c++ conversion] "; 00276 else if (D->isImplicit()) 00277 Out << "(c++ conversion) "; 00278 else 00279 Out << "<c++ conversion> "; 00280 Out << *D; 00281 // Check the semantic DC. 00282 const DeclContext* SemaDC = D->getDeclContext(); 00283 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 00284 if (SemaDC != LexicalDC) 00285 Out << " [[" << SemaDC << "]]"; 00286 break; 00287 } 00288 00289 default: 00290 llvm_unreachable("a decl that inherits DeclContext isn't handled"); 00291 } 00292 00293 Out << "\n"; 00294 00295 // Print decls in the DeclContext. 00296 for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end(); 00297 I != E; ++I) { 00298 for (unsigned i = 0; i < Indentation; ++i) 00299 Out << " "; 00300 00301 Decl::Kind DK = I->getKind(); 00302 switch (DK) { 00303 case Decl::Namespace: 00304 case Decl::Enum: 00305 case Decl::Record: 00306 case Decl::CXXRecord: 00307 case Decl::ObjCMethod: 00308 case Decl::ObjCInterface: 00309 case Decl::ObjCCategory: 00310 case Decl::ObjCProtocol: 00311 case Decl::ObjCImplementation: 00312 case Decl::ObjCCategoryImpl: 00313 case Decl::LinkageSpec: 00314 case Decl::Block: 00315 case Decl::Function: 00316 case Decl::CXXMethod: 00317 case Decl::CXXConstructor: 00318 case Decl::CXXDestructor: 00319 case Decl::CXXConversion: 00320 { 00321 DeclContext* DC = cast<DeclContext>(*I); 00322 PrintDeclContext(DC, Indentation+2); 00323 break; 00324 } 00325 case Decl::IndirectField: { 00326 IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(*I); 00327 Out << "<IndirectField> " << *IFD << '\n'; 00328 break; 00329 } 00330 case Decl::Label: { 00331 LabelDecl *LD = cast<LabelDecl>(*I); 00332 Out << "<Label> " << *LD << '\n'; 00333 break; 00334 } 00335 case Decl::Field: { 00336 FieldDecl *FD = cast<FieldDecl>(*I); 00337 Out << "<field> " << *FD << '\n'; 00338 break; 00339 } 00340 case Decl::Typedef: 00341 case Decl::TypeAlias: { 00342 TypedefNameDecl* TD = cast<TypedefNameDecl>(*I); 00343 Out << "<typedef> " << *TD << '\n'; 00344 break; 00345 } 00346 case Decl::EnumConstant: { 00347 EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I); 00348 Out << "<enum constant> " << *ECD << '\n'; 00349 break; 00350 } 00351 case Decl::Var: { 00352 VarDecl* VD = cast<VarDecl>(*I); 00353 Out << "<var> " << *VD << '\n'; 00354 break; 00355 } 00356 case Decl::ImplicitParam: { 00357 ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I); 00358 Out << "<implicit parameter> " << *IPD << '\n'; 00359 break; 00360 } 00361 case Decl::ParmVar: { 00362 ParmVarDecl* PVD = cast<ParmVarDecl>(*I); 00363 Out << "<parameter> " << *PVD << '\n'; 00364 break; 00365 } 00366 case Decl::ObjCProperty: { 00367 ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I); 00368 Out << "<objc property> " << *OPD << '\n'; 00369 break; 00370 } 00371 case Decl::FunctionTemplate: { 00372 FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I); 00373 Out << "<function template> " << *FTD << '\n'; 00374 break; 00375 } 00376 case Decl::FileScopeAsm: { 00377 Out << "<file-scope asm>\n"; 00378 break; 00379 } 00380 case Decl::UsingDirective: { 00381 Out << "<using directive>\n"; 00382 break; 00383 } 00384 case Decl::NamespaceAlias: { 00385 NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I); 00386 Out << "<namespace alias> " << *NAD << '\n'; 00387 break; 00388 } 00389 case Decl::ClassTemplate: { 00390 ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I); 00391 Out << "<class template> " << *CTD << '\n'; 00392 break; 00393 } 00394 default: 00395 Out << "DeclKind: " << DK << '"' << *I << "\"\n"; 00396 llvm_unreachable("decl unhandled"); 00397 } 00398 } 00399 } 00400 ASTConsumer *clang::CreateDeclContextPrinter() { 00401 return new DeclContextPrinter(); 00402 } 00403 00404 //===----------------------------------------------------------------------===// 00405 /// ASTDumperXML - In-depth XML dumping. 00406 00407 namespace { 00408 class ASTDumpXML : public ASTConsumer { 00409 raw_ostream &OS; 00410 00411 public: 00412 ASTDumpXML(raw_ostream &OS) : OS(OS) {} 00413 00414 void HandleTranslationUnit(ASTContext &C) { 00415 C.getTranslationUnitDecl()->dumpXML(OS); 00416 } 00417 }; 00418 } 00419 00420 ASTConsumer *clang::CreateASTDumperXML(raw_ostream &OS) { 00421 return new ASTDumpXML(OS); 00422 }