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