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