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