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/SourceManager.h" 23 #include "llvm/Support/Path.h" 24 #include "llvm/Support/Timer.h" 25 #include "llvm/Support/raw_ostream.h" 26 using namespace clang; 27 28 //===----------------------------------------------------------------------===// 29 /// ASTPrinter - Pretty-printer and dumper of ASTs 30 31 namespace { 32 class ASTPrinter : public ASTConsumer, 33 public RecursiveASTVisitor<ASTPrinter> { 34 typedef RecursiveASTVisitor<ASTPrinter> base; 35 36 public: 37 enum Kind { DumpFull, Dump, Print, None }; 38 ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K, StringRef FilterString, 39 bool DumpLookups = false) 40 : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)), 41 OutputKind(K), FilterString(FilterString), DumpLookups(DumpLookups) {} 42 43 void HandleTranslationUnit(ASTContext &Context) override { 44 TranslationUnitDecl *D = Context.getTranslationUnitDecl(); 45 46 if (FilterString.empty()) 47 return print(D); 48 49 TraverseDecl(D); 50 } 51 52 bool shouldWalkTypesOfTypeLocs() const { return false; } 53 54 bool TraverseDecl(Decl *D) { 55 if (D && filterMatches(D)) { 56 bool ShowColors = Out.has_colors(); 57 if (ShowColors) 58 Out.changeColor(raw_ostream::BLUE); 59 Out << (OutputKind != Print ? "Dumping " : "Printing ") << getName(D) 60 << ":\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 if (DC == DC->getPrimaryContext()) 84 DC->dumpLookups(Out, OutputKind != None, OutputKind == DumpFull); 85 else 86 Out << "Lookup map is in primary DeclContext " 87 << DC->getPrimaryContext() << "\n"; 88 } else 89 Out << "Not a DeclContext\n"; 90 } else if (OutputKind == Print) { 91 PrintingPolicy Policy(D->getASTContext().getLangOpts()); 92 D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true); 93 } else if (OutputKind != None) 94 D->dump(Out, OutputKind == DumpFull); 95 } 96 97 raw_ostream &Out; 98 std::unique_ptr<raw_ostream> OwnedOut; 99 100 /// How to output individual declarations. 101 Kind OutputKind; 102 103 /// Which declarations or DeclContexts to display. 104 std::string FilterString; 105 106 /// Whether the primary output is lookup results or declarations. Individual 107 /// results will be output with a format determined by OutputKind. This is 108 /// incompatible with OutputKind == Print. 109 bool DumpLookups; 110 }; 111 112 class ASTDeclNodeLister : public ASTConsumer, 113 public RecursiveASTVisitor<ASTDeclNodeLister> { 114 public: 115 ASTDeclNodeLister(raw_ostream *Out = nullptr) 116 : Out(Out ? *Out : llvm::outs()) {} 117 118 void HandleTranslationUnit(ASTContext &Context) override { 119 TraverseDecl(Context.getTranslationUnitDecl()); 120 } 121 122 bool shouldWalkTypesOfTypeLocs() const { return false; } 123 124 bool VisitNamedDecl(NamedDecl *D) { 125 D->printQualifiedName(Out); 126 Out << '\n'; 127 return true; 128 } 129 130 private: 131 raw_ostream &Out; 132 }; 133 } // end anonymous namespace 134 135 std::unique_ptr<ASTConsumer> 136 clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out, 137 StringRef FilterString) { 138 return llvm::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print, 139 FilterString); 140 } 141 142 std::unique_ptr<ASTConsumer> 143 clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, 144 StringRef FilterString, 145 bool DumpDecls, 146 bool Deserialize, 147 bool DumpLookups) { 148 assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump"); 149 return llvm::make_unique<ASTPrinter>(std::move(Out), 150 Deserialize ? ASTPrinter::DumpFull : 151 DumpDecls ? ASTPrinter::Dump : 152 ASTPrinter::None, 153 FilterString, DumpLookups); 154 } 155 156 std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() { 157 return llvm::make_unique<ASTDeclNodeLister>(nullptr); 158 } 159 160 //===----------------------------------------------------------------------===// 161 /// ASTViewer - AST Visualization 162 163 namespace { 164 class ASTViewer : public ASTConsumer { 165 ASTContext *Context; 166 public: 167 void Initialize(ASTContext &Context) override { 168 this->Context = &Context; 169 } 170 171 bool HandleTopLevelDecl(DeclGroupRef D) override { 172 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) 173 HandleTopLevelSingleDecl(*I); 174 return true; 175 } 176 177 void HandleTopLevelSingleDecl(Decl *D); 178 }; 179 } 180 181 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { 182 if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { 183 D->print(llvm::errs()); 184 185 if (Stmt *Body = D->getBody()) { 186 llvm::errs() << '\n'; 187 Body->viewAST(); 188 llvm::errs() << '\n'; 189 } 190 } 191 } 192 193 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() { 194 return llvm::make_unique<ASTViewer>(); 195 } 196 197 //===----------------------------------------------------------------------===// 198 /// DeclContextPrinter - Decl and DeclContext Visualization 199 200 namespace { 201 202 class DeclContextPrinter : public ASTConsumer { 203 raw_ostream& Out; 204 public: 205 DeclContextPrinter() : Out(llvm::errs()) {} 206 207 void HandleTranslationUnit(ASTContext &C) override { 208 PrintDeclContext(C.getTranslationUnitDecl(), 4); 209 } 210 211 void PrintDeclContext(const DeclContext* DC, unsigned Indentation); 212 }; 213 } // end anonymous namespace 214 215 void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, 216 unsigned Indentation) { 217 // Print DeclContext name. 218 switch (DC->getDeclKind()) { 219 case Decl::TranslationUnit: 220 Out << "[translation unit] " << DC; 221 break; 222 case Decl::Namespace: { 223 Out << "[namespace] "; 224 const NamespaceDecl* ND = cast<NamespaceDecl>(DC); 225 Out << *ND; 226 break; 227 } 228 case Decl::Enum: { 229 const EnumDecl* ED = cast<EnumDecl>(DC); 230 if (ED->isCompleteDefinition()) 231 Out << "[enum] "; 232 else 233 Out << "<enum> "; 234 Out << *ED; 235 break; 236 } 237 case Decl::Record: { 238 const RecordDecl* RD = cast<RecordDecl>(DC); 239 if (RD->isCompleteDefinition()) 240 Out << "[struct] "; 241 else 242 Out << "<struct> "; 243 Out << *RD; 244 break; 245 } 246 case Decl::CXXRecord: { 247 const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC); 248 if (RD->isCompleteDefinition()) 249 Out << "[class] "; 250 else 251 Out << "<class> "; 252 Out << *RD << ' ' << DC; 253 break; 254 } 255 case Decl::ObjCMethod: 256 Out << "[objc method]"; 257 break; 258 case Decl::ObjCInterface: 259 Out << "[objc interface]"; 260 break; 261 case Decl::ObjCCategory: 262 Out << "[objc category]"; 263 break; 264 case Decl::ObjCProtocol: 265 Out << "[objc protocol]"; 266 break; 267 case Decl::ObjCImplementation: 268 Out << "[objc implementation]"; 269 break; 270 case Decl::ObjCCategoryImpl: 271 Out << "[objc categoryimpl]"; 272 break; 273 case Decl::LinkageSpec: 274 Out << "[linkage spec]"; 275 break; 276 case Decl::Block: 277 Out << "[block]"; 278 break; 279 case Decl::Function: { 280 const FunctionDecl* FD = cast<FunctionDecl>(DC); 281 if (FD->doesThisDeclarationHaveABody()) 282 Out << "[function] "; 283 else 284 Out << "<function> "; 285 Out << *FD; 286 // Print the parameters. 287 Out << "("; 288 bool PrintComma = false; 289 for (auto I : FD->parameters()) { 290 if (PrintComma) 291 Out << ", "; 292 else 293 PrintComma = true; 294 Out << *I; 295 } 296 Out << ")"; 297 break; 298 } 299 case Decl::CXXMethod: { 300 const CXXMethodDecl* D = cast<CXXMethodDecl>(DC); 301 if (D->isOutOfLine()) 302 Out << "[c++ method] "; 303 else if (D->isImplicit()) 304 Out << "(c++ method) "; 305 else 306 Out << "<c++ method> "; 307 Out << *D; 308 // Print the parameters. 309 Out << "("; 310 bool PrintComma = false; 311 for (ParmVarDecl *Parameter : D->parameters()) { 312 if (PrintComma) 313 Out << ", "; 314 else 315 PrintComma = true; 316 Out << *Parameter; 317 } 318 Out << ")"; 319 320 // Check the semantic DeclContext. 321 const DeclContext* SemaDC = D->getDeclContext(); 322 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 323 if (SemaDC != LexicalDC) 324 Out << " [[" << SemaDC << "]]"; 325 326 break; 327 } 328 case Decl::CXXConstructor: { 329 const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC); 330 if (D->isOutOfLine()) 331 Out << "[c++ ctor] "; 332 else if (D->isImplicit()) 333 Out << "(c++ ctor) "; 334 else 335 Out << "<c++ ctor> "; 336 Out << *D; 337 // Print the parameters. 338 Out << "("; 339 bool PrintComma = false; 340 for (ParmVarDecl *Parameter : D->parameters()) { 341 if (PrintComma) 342 Out << ", "; 343 else 344 PrintComma = true; 345 Out << *Parameter; 346 } 347 Out << ")"; 348 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 case Decl::CXXDestructor: { 357 const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC); 358 if (D->isOutOfLine()) 359 Out << "[c++ dtor] "; 360 else if (D->isImplicit()) 361 Out << "(c++ dtor) "; 362 else 363 Out << "<c++ dtor> "; 364 Out << *D; 365 // Check the semantic DC. 366 const DeclContext* SemaDC = D->getDeclContext(); 367 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 368 if (SemaDC != LexicalDC) 369 Out << " [[" << SemaDC << "]]"; 370 break; 371 } 372 case Decl::CXXConversion: { 373 const CXXConversionDecl* D = cast<CXXConversionDecl>(DC); 374 if (D->isOutOfLine()) 375 Out << "[c++ conversion] "; 376 else if (D->isImplicit()) 377 Out << "(c++ conversion) "; 378 else 379 Out << "<c++ conversion> "; 380 Out << *D; 381 // Check the semantic DC. 382 const DeclContext* SemaDC = D->getDeclContext(); 383 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 384 if (SemaDC != LexicalDC) 385 Out << " [[" << SemaDC << "]]"; 386 break; 387 } 388 389 case Decl::ClassTemplateSpecialization: { 390 const auto *CTSD = cast<ClassTemplateSpecializationDecl>(DC); 391 if (CTSD->isCompleteDefinition()) 392 Out << "[class template specialization] "; 393 else 394 Out << "<class template specialization> "; 395 Out << *CTSD; 396 break; 397 } 398 399 case Decl::ClassTemplatePartialSpecialization: { 400 const auto *CTPSD = cast<ClassTemplatePartialSpecializationDecl>(DC); 401 if (CTPSD->isCompleteDefinition()) 402 Out << "[class template partial specialization] "; 403 else 404 Out << "<class template partial specialization> "; 405 Out << *CTPSD; 406 break; 407 } 408 409 default: 410 llvm_unreachable("a decl that inherits DeclContext isn't handled"); 411 } 412 413 Out << "\n"; 414 415 // Print decls in the DeclContext. 416 for (auto *I : DC->decls()) { 417 for (unsigned i = 0; i < Indentation; ++i) 418 Out << " "; 419 420 Decl::Kind DK = I->getKind(); 421 switch (DK) { 422 case Decl::Namespace: 423 case Decl::Enum: 424 case Decl::Record: 425 case Decl::CXXRecord: 426 case Decl::ObjCMethod: 427 case Decl::ObjCInterface: 428 case Decl::ObjCCategory: 429 case Decl::ObjCProtocol: 430 case Decl::ObjCImplementation: 431 case Decl::ObjCCategoryImpl: 432 case Decl::LinkageSpec: 433 case Decl::Block: 434 case Decl::Function: 435 case Decl::CXXMethod: 436 case Decl::CXXConstructor: 437 case Decl::CXXDestructor: 438 case Decl::CXXConversion: 439 case Decl::ClassTemplateSpecialization: 440 case Decl::ClassTemplatePartialSpecialization: { 441 DeclContext* DC = cast<DeclContext>(I); 442 PrintDeclContext(DC, Indentation+2); 443 break; 444 } 445 case Decl::IndirectField: { 446 IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(I); 447 Out << "<IndirectField> " << *IFD << '\n'; 448 break; 449 } 450 case Decl::Label: { 451 LabelDecl *LD = cast<LabelDecl>(I); 452 Out << "<Label> " << *LD << '\n'; 453 break; 454 } 455 case Decl::Field: { 456 FieldDecl *FD = cast<FieldDecl>(I); 457 Out << "<field> " << *FD << '\n'; 458 break; 459 } 460 case Decl::Typedef: 461 case Decl::TypeAlias: { 462 TypedefNameDecl* TD = cast<TypedefNameDecl>(I); 463 Out << "<typedef> " << *TD << '\n'; 464 break; 465 } 466 case Decl::EnumConstant: { 467 EnumConstantDecl* ECD = cast<EnumConstantDecl>(I); 468 Out << "<enum constant> " << *ECD << '\n'; 469 break; 470 } 471 case Decl::Var: { 472 VarDecl* VD = cast<VarDecl>(I); 473 Out << "<var> " << *VD << '\n'; 474 break; 475 } 476 case Decl::ImplicitParam: { 477 ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(I); 478 Out << "<implicit parameter> " << *IPD << '\n'; 479 break; 480 } 481 case Decl::ParmVar: { 482 ParmVarDecl* PVD = cast<ParmVarDecl>(I); 483 Out << "<parameter> " << *PVD << '\n'; 484 break; 485 } 486 case Decl::ObjCProperty: { 487 ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(I); 488 Out << "<objc property> " << *OPD << '\n'; 489 break; 490 } 491 case Decl::FunctionTemplate: { 492 FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(I); 493 Out << "<function template> " << *FTD << '\n'; 494 break; 495 } 496 case Decl::FileScopeAsm: { 497 Out << "<file-scope asm>\n"; 498 break; 499 } 500 case Decl::UsingDirective: { 501 Out << "<using directive>\n"; 502 break; 503 } 504 case Decl::NamespaceAlias: { 505 NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(I); 506 Out << "<namespace alias> " << *NAD << '\n'; 507 break; 508 } 509 case Decl::ClassTemplate: { 510 ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(I); 511 Out << "<class template> " << *CTD << '\n'; 512 break; 513 } 514 case Decl::OMPThreadPrivate: { 515 Out << "<omp threadprivate> " << '"' << I << "\"\n"; 516 break; 517 } 518 case Decl::Friend: { 519 Out << "<friend>"; 520 if (const NamedDecl *ND = cast<FriendDecl>(I)->getFriendDecl()) 521 Out << ' ' << *ND; 522 Out << "\n"; 523 break; 524 } 525 case Decl::Using: { 526 Out << "<using> " << *cast<UsingDecl>(I) << "\n"; 527 break; 528 } 529 case Decl::UsingShadow: { 530 Out << "<using shadow> " << *cast<UsingShadowDecl>(I) << "\n"; 531 break; 532 } 533 case Decl::Empty: { 534 Out << "<empty>\n"; 535 break; 536 } 537 case Decl::AccessSpec: { 538 Out << "<access specifier>\n"; 539 break; 540 } 541 case Decl::VarTemplate: { 542 Out << "<var template> " << *cast<VarTemplateDecl>(I) << "\n"; 543 break; 544 } 545 case Decl::StaticAssert: { 546 Out << "<static assert>\n"; 547 break; 548 } 549 default: 550 Out << "DeclKind: " << DK << '"' << I << "\"\n"; 551 llvm_unreachable("decl unhandled"); 552 } 553 } 554 } 555 std::unique_ptr<ASTConsumer> clang::CreateDeclContextPrinter() { 556 return llvm::make_unique<DeclContextPrinter>(); 557 } 558