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