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