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