ASTConsumers.cpp revision 208954
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/Frontend/DocumentXML.h" 16#include "clang/Frontend/PathDiagnosticClients.h" 17#include "clang/Basic/Diagnostic.h" 18#include "clang/Basic/SourceManager.h" 19#include "clang/Basic/FileManager.h" 20#include "clang/AST/AST.h" 21#include "clang/AST/ASTConsumer.h" 22#include "clang/AST/ASTContext.h" 23#include "clang/AST/RecordLayout.h" 24#include "clang/AST/PrettyPrinter.h" 25#include "clang/CodeGen/ModuleBuilder.h" 26#include "llvm/Module.h" 27#include "llvm/Support/Timer.h" 28#include "llvm/Support/raw_ostream.h" 29#include "llvm/System/Path.h" 30using namespace clang; 31 32//===----------------------------------------------------------------------===// 33/// ASTPrinter - Pretty-printer and dumper of ASTs 34 35namespace { 36 class ASTPrinter : public ASTConsumer { 37 llvm::raw_ostream &Out; 38 bool Dump; 39 40 public: 41 ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false) 42 : Out(o? *o : llvm::errs()), Dump(Dump) { } 43 44 virtual void HandleTranslationUnit(ASTContext &Context) { 45 PrintingPolicy Policy = Context.PrintingPolicy; 46 Policy.Dump = Dump; 47 Context.getTranslationUnitDecl()->print(Out, Policy); 48 } 49 }; 50} // end anonymous namespace 51 52ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) { 53 return new ASTPrinter(out); 54} 55 56//===----------------------------------------------------------------------===// 57/// ASTPrinterXML - XML-printer of ASTs 58 59namespace { 60 class ASTPrinterXML : public ASTConsumer { 61 DocumentXML Doc; 62 63 public: 64 ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {} 65 66 void Initialize(ASTContext &Context) { 67 Doc.initialize(Context); 68 } 69 70 virtual void HandleTranslationUnit(ASTContext &Ctx) { 71 Doc.addSubNode("TranslationUnit"); 72 for (DeclContext::decl_iterator 73 D = Ctx.getTranslationUnitDecl()->decls_begin(), 74 DEnd = Ctx.getTranslationUnitDecl()->decls_end(); 75 D != DEnd; 76 ++D) 77 Doc.PrintDecl(*D); 78 Doc.toParent(); 79 Doc.finalize(); 80 } 81 }; 82} // end anonymous namespace 83 84 85ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) { 86 return new ASTPrinterXML(out ? *out : llvm::outs()); 87} 88 89ASTConsumer *clang::CreateASTDumper() { 90 return new ASTPrinter(0, true); 91} 92 93//===----------------------------------------------------------------------===// 94/// ASTViewer - AST Visualization 95 96namespace { 97 class ASTViewer : public ASTConsumer { 98 ASTContext *Context; 99 public: 100 void Initialize(ASTContext &Context) { 101 this->Context = &Context; 102 } 103 104 virtual void HandleTopLevelDecl(DeclGroupRef D) { 105 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) 106 HandleTopLevelSingleDecl(*I); 107 } 108 109 void HandleTopLevelSingleDecl(Decl *D); 110 }; 111} 112 113void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { 114 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 115 FD->print(llvm::errs()); 116 117 if (Stmt *Body = FD->getBody()) { 118 llvm::errs() << '\n'; 119 Body->viewAST(); 120 llvm::errs() << '\n'; 121 } 122 return; 123 } 124 125 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 126 MD->print(llvm::errs()); 127 128 if (MD->getBody()) { 129 llvm::errs() << '\n'; 130 MD->getBody()->viewAST(); 131 llvm::errs() << '\n'; 132 } 133 } 134} 135 136 137ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); } 138 139//===----------------------------------------------------------------------===// 140/// DeclContextPrinter - Decl and DeclContext Visualization 141 142namespace { 143 144class DeclContextPrinter : public ASTConsumer { 145 llvm::raw_ostream& Out; 146public: 147 DeclContextPrinter() : Out(llvm::errs()) {} 148 149 void HandleTranslationUnit(ASTContext &C) { 150 PrintDeclContext(C.getTranslationUnitDecl(), 4); 151 } 152 153 void PrintDeclContext(const DeclContext* DC, unsigned Indentation); 154}; 155} // end anonymous namespace 156 157void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, 158 unsigned Indentation) { 159 // Print DeclContext name. 160 switch (DC->getDeclKind()) { 161 case Decl::TranslationUnit: 162 Out << "[translation unit] " << DC; 163 break; 164 case Decl::Namespace: { 165 Out << "[namespace] "; 166 const NamespaceDecl* ND = cast<NamespaceDecl>(DC); 167 Out << ND; 168 break; 169 } 170 case Decl::Enum: { 171 const EnumDecl* ED = cast<EnumDecl>(DC); 172 if (ED->isDefinition()) 173 Out << "[enum] "; 174 else 175 Out << "<enum> "; 176 Out << ED; 177 break; 178 } 179 case Decl::Record: { 180 const RecordDecl* RD = cast<RecordDecl>(DC); 181 if (RD->isDefinition()) 182 Out << "[struct] "; 183 else 184 Out << "<struct> "; 185 Out << RD; 186 break; 187 } 188 case Decl::CXXRecord: { 189 const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC); 190 if (RD->isDefinition()) 191 Out << "[class] "; 192 else 193 Out << "<class> "; 194 Out << RD << ' ' << DC; 195 break; 196 } 197 case Decl::ObjCMethod: 198 Out << "[objc method]"; 199 break; 200 case Decl::ObjCInterface: 201 Out << "[objc interface]"; 202 break; 203 case Decl::ObjCCategory: 204 Out << "[objc category]"; 205 break; 206 case Decl::ObjCProtocol: 207 Out << "[objc protocol]"; 208 break; 209 case Decl::ObjCImplementation: 210 Out << "[objc implementation]"; 211 break; 212 case Decl::ObjCCategoryImpl: 213 Out << "[objc categoryimpl]"; 214 break; 215 case Decl::LinkageSpec: 216 Out << "[linkage spec]"; 217 break; 218 case Decl::Block: 219 Out << "[block]"; 220 break; 221 case Decl::Function: { 222 const FunctionDecl* FD = cast<FunctionDecl>(DC); 223 if (FD->isThisDeclarationADefinition()) 224 Out << "[function] "; 225 else 226 Out << "<function> "; 227 Out << FD; 228 // Print the parameters. 229 Out << "("; 230 bool PrintComma = false; 231 for (FunctionDecl::param_const_iterator I = FD->param_begin(), 232 E = FD->param_end(); I != E; ++I) { 233 if (PrintComma) 234 Out << ", "; 235 else 236 PrintComma = true; 237 Out << *I; 238 } 239 Out << ")"; 240 break; 241 } 242 case Decl::CXXMethod: { 243 const CXXMethodDecl* D = cast<CXXMethodDecl>(DC); 244 if (D->isOutOfLine()) 245 Out << "[c++ method] "; 246 else if (D->isImplicit()) 247 Out << "(c++ method) "; 248 else 249 Out << "<c++ method> "; 250 Out << D; 251 // Print the parameters. 252 Out << "("; 253 bool PrintComma = false; 254 for (FunctionDecl::param_const_iterator I = D->param_begin(), 255 E = D->param_end(); I != E; ++I) { 256 if (PrintComma) 257 Out << ", "; 258 else 259 PrintComma = true; 260 Out << *I; 261 } 262 Out << ")"; 263 264 // Check the semantic DeclContext. 265 const DeclContext* SemaDC = D->getDeclContext(); 266 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 267 if (SemaDC != LexicalDC) 268 Out << " [[" << SemaDC << "]]"; 269 270 break; 271 } 272 case Decl::CXXConstructor: { 273 const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC); 274 if (D->isOutOfLine()) 275 Out << "[c++ ctor] "; 276 else if (D->isImplicit()) 277 Out << "(c++ ctor) "; 278 else 279 Out << "<c++ ctor> "; 280 Out << D; 281 // Print the parameters. 282 Out << "("; 283 bool PrintComma = false; 284 for (FunctionDecl::param_const_iterator I = D->param_begin(), 285 E = D->param_end(); I != E; ++I) { 286 if (PrintComma) 287 Out << ", "; 288 else 289 PrintComma = true; 290 Out << *I; 291 } 292 Out << ")"; 293 294 // Check the semantic DC. 295 const DeclContext* SemaDC = D->getDeclContext(); 296 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 297 if (SemaDC != LexicalDC) 298 Out << " [[" << SemaDC << "]]"; 299 break; 300 } 301 case Decl::CXXDestructor: { 302 const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC); 303 if (D->isOutOfLine()) 304 Out << "[c++ dtor] "; 305 else if (D->isImplicit()) 306 Out << "(c++ dtor) "; 307 else 308 Out << "<c++ dtor> "; 309 Out << D; 310 // Check the semantic DC. 311 const DeclContext* SemaDC = D->getDeclContext(); 312 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 313 if (SemaDC != LexicalDC) 314 Out << " [[" << SemaDC << "]]"; 315 break; 316 } 317 case Decl::CXXConversion: { 318 const CXXConversionDecl* D = cast<CXXConversionDecl>(DC); 319 if (D->isOutOfLine()) 320 Out << "[c++ conversion] "; 321 else if (D->isImplicit()) 322 Out << "(c++ conversion) "; 323 else 324 Out << "<c++ conversion> "; 325 Out << D; 326 // Check the semantic DC. 327 const DeclContext* SemaDC = D->getDeclContext(); 328 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 329 if (SemaDC != LexicalDC) 330 Out << " [[" << SemaDC << "]]"; 331 break; 332 } 333 334 default: 335 assert(0 && "a decl that inherits DeclContext isn't handled"); 336 } 337 338 Out << "\n"; 339 340 // Print decls in the DeclContext. 341 for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end(); 342 I != E; ++I) { 343 for (unsigned i = 0; i < Indentation; ++i) 344 Out << " "; 345 346 Decl::Kind DK = I->getKind(); 347 switch (DK) { 348 case Decl::Namespace: 349 case Decl::Enum: 350 case Decl::Record: 351 case Decl::CXXRecord: 352 case Decl::ObjCMethod: 353 case Decl::ObjCInterface: 354 case Decl::ObjCCategory: 355 case Decl::ObjCProtocol: 356 case Decl::ObjCImplementation: 357 case Decl::ObjCCategoryImpl: 358 case Decl::LinkageSpec: 359 case Decl::Block: 360 case Decl::Function: 361 case Decl::CXXMethod: 362 case Decl::CXXConstructor: 363 case Decl::CXXDestructor: 364 case Decl::CXXConversion: 365 { 366 DeclContext* DC = cast<DeclContext>(*I); 367 PrintDeclContext(DC, Indentation+2); 368 break; 369 } 370 case Decl::Field: { 371 FieldDecl* FD = cast<FieldDecl>(*I); 372 Out << "<field> " << FD << '\n'; 373 break; 374 } 375 case Decl::Typedef: { 376 TypedefDecl* TD = cast<TypedefDecl>(*I); 377 Out << "<typedef> " << TD << '\n'; 378 break; 379 } 380 case Decl::EnumConstant: { 381 EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I); 382 Out << "<enum constant> " << ECD << '\n'; 383 break; 384 } 385 case Decl::Var: { 386 VarDecl* VD = cast<VarDecl>(*I); 387 Out << "<var> " << VD << '\n'; 388 break; 389 } 390 case Decl::ImplicitParam: { 391 ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I); 392 Out << "<implicit parameter> " << IPD << '\n'; 393 break; 394 } 395 case Decl::ParmVar: { 396 ParmVarDecl* PVD = cast<ParmVarDecl>(*I); 397 Out << "<parameter> " << PVD << '\n'; 398 break; 399 } 400 case Decl::ObjCProperty: { 401 ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I); 402 Out << "<objc property> " << OPD << '\n'; 403 break; 404 } 405 case Decl::FunctionTemplate: { 406 FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I); 407 Out << "<function template> " << FTD << '\n'; 408 break; 409 } 410 case Decl::FileScopeAsm: { 411 Out << "<file-scope asm>\n"; 412 break; 413 } 414 case Decl::UsingDirective: { 415 Out << "<using directive>\n"; 416 break; 417 } 418 case Decl::NamespaceAlias: { 419 NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I); 420 Out << "<namespace alias> " << NAD << '\n'; 421 break; 422 } 423 case Decl::ClassTemplate: { 424 ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I); 425 Out << "<class template> " << CTD << '\n'; 426 break; 427 } 428 default: 429 Out << "DeclKind: " << DK << '"' << *I << "\"\n"; 430 assert(0 && "decl unhandled"); 431 } 432 } 433} 434ASTConsumer *clang::CreateDeclContextPrinter() { 435 return new DeclContextPrinter(); 436} 437 438//===----------------------------------------------------------------------===// 439/// InheritanceViewer - C++ Inheritance Visualization 440 441namespace { 442class InheritanceViewer : public ASTConsumer { 443 const std::string clsname; 444public: 445 InheritanceViewer(const std::string& cname) : clsname(cname) {} 446 447 void HandleTranslationUnit(ASTContext &C) { 448 for (ASTContext::type_iterator I=C.types_begin(),E=C.types_end(); I!=E; ++I) 449 if (RecordType *T = dyn_cast<RecordType>(*I)) { 450 if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(T->getDecl())) { 451 // FIXME: This lookup needs to be generalized to handle namespaces and 452 // (when we support them) templates. 453 if (D->getNameAsString() == clsname) { 454 D->viewInheritance(C); 455 } 456 } 457 } 458 } 459}; 460} 461 462ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) { 463 return new InheritanceViewer(clsname); 464} 465