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