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