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