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