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/IR/Module.h" 25 #include "llvm/Support/Path.h" 26 #include "llvm/Support/Timer.h" 27 #include "llvm/Support/raw_ostream.h" 28 using namespace clang; 29 30 //===----------------------------------------------------------------------===// 31 /// ASTPrinter - Pretty-printer and dumper of ASTs 32 33 namespace { 34 class ASTPrinter : public ASTConsumer, 35 public RecursiveASTVisitor<ASTPrinter> { 36 typedef RecursiveASTVisitor<ASTPrinter> base; 37 38 public: 39 ASTPrinter(raw_ostream *Out = nullptr, bool Dump = false, 40 StringRef FilterString = "", bool DumpLookups = false) 41 : Out(Out ? *Out : llvm::outs()), Dump(Dump), 42 FilterString(FilterString), DumpLookups(DumpLookups) {} 43 44 void HandleTranslationUnit(ASTContext &Context) override { 45 TranslationUnitDecl *D = Context.getTranslationUnitDecl(); 46 47 if (FilterString.empty()) 48 return print(D); 49 50 TraverseDecl(D); 51 } 52 53 bool shouldWalkTypesOfTypeLocs() const { return false; } 54 55 bool TraverseDecl(Decl *D) { 56 if (D && filterMatches(D)) { 57 bool ShowColors = Out.has_colors(); 58 if (ShowColors) 59 Out.changeColor(raw_ostream::BLUE); 60 Out << ((Dump || DumpLookups) ? "Dumping " : "Printing ") << getName(D) 61 << ":\n"; 62 if (ShowColors) 63 Out.resetColor(); 64 print(D); 65 Out << "\n"; 66 // Don't traverse child nodes to avoid output duplication. 67 return true; 68 } 69 return base::TraverseDecl(D); 70 } 71 72 private: 73 std::string getName(Decl *D) { 74 if (isa<NamedDecl>(D)) 75 return cast<NamedDecl>(D)->getQualifiedNameAsString(); 76 return ""; 77 } 78 bool filterMatches(Decl *D) { 79 return getName(D).find(FilterString) != std::string::npos; 80 } 81 void print(Decl *D) { 82 if (DumpLookups) { 83 if (DeclContext *DC = dyn_cast<DeclContext>(D)) { 84 if (DC == DC->getPrimaryContext()) 85 DC->dumpLookups(Out, Dump); 86 else 87 Out << "Lookup map is in primary DeclContext " 88 << DC->getPrimaryContext() << "\n"; 89 } else 90 Out << "Not a DeclContext\n"; 91 } else if (Dump) 92 D->dump(Out); 93 else 94 D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true); 95 } 96 97 raw_ostream &Out; 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> clang::CreateASTPrinter(raw_ostream *Out, 127 StringRef FilterString) { 128 return llvm::make_unique<ASTPrinter>(Out, /*Dump=*/false, FilterString); 129 } 130 131 std::unique_ptr<ASTConsumer> clang::CreateASTDumper(StringRef FilterString, 132 bool DumpDecls, 133 bool DumpLookups) { 134 assert((DumpDecls || DumpLookups) && "nothing to dump"); 135 return llvm::make_unique<ASTPrinter>(nullptr, DumpDecls, FilterString, 136 DumpLookups); 137 } 138 139 std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() { 140 return llvm::make_unique<ASTDeclNodeLister>(nullptr); 141 } 142 143 //===----------------------------------------------------------------------===// 144 /// ASTViewer - AST Visualization 145 146 namespace { 147 class ASTViewer : public ASTConsumer { 148 ASTContext *Context; 149 public: 150 void Initialize(ASTContext &Context) override { 151 this->Context = &Context; 152 } 153 154 bool HandleTopLevelDecl(DeclGroupRef D) override { 155 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) 156 HandleTopLevelSingleDecl(*I); 157 return true; 158 } 159 160 void HandleTopLevelSingleDecl(Decl *D); 161 }; 162 } 163 164 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { 165 if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) { 166 D->print(llvm::errs()); 167 168 if (Stmt *Body = D->getBody()) { 169 llvm::errs() << '\n'; 170 Body->viewAST(); 171 llvm::errs() << '\n'; 172 } 173 } 174 } 175 176 std::unique_ptr<ASTConsumer> clang::CreateASTViewer() { 177 return llvm::make_unique<ASTViewer>(); 178 } 179 180 //===----------------------------------------------------------------------===// 181 /// DeclContextPrinter - Decl and DeclContext Visualization 182 183 namespace { 184 185 class DeclContextPrinter : public ASTConsumer { 186 raw_ostream& Out; 187 public: 188 DeclContextPrinter() : Out(llvm::errs()) {} 189 190 void HandleTranslationUnit(ASTContext &C) override { 191 PrintDeclContext(C.getTranslationUnitDecl(), 4); 192 } 193 194 void PrintDeclContext(const DeclContext* DC, unsigned Indentation); 195 }; 196 } // end anonymous namespace 197 198 void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, 199 unsigned Indentation) { 200 // Print DeclContext name. 201 switch (DC->getDeclKind()) { 202 case Decl::TranslationUnit: 203 Out << "[translation unit] " << DC; 204 break; 205 case Decl::Namespace: { 206 Out << "[namespace] "; 207 const NamespaceDecl* ND = cast<NamespaceDecl>(DC); 208 Out << *ND; 209 break; 210 } 211 case Decl::Enum: { 212 const EnumDecl* ED = cast<EnumDecl>(DC); 213 if (ED->isCompleteDefinition()) 214 Out << "[enum] "; 215 else 216 Out << "<enum> "; 217 Out << *ED; 218 break; 219 } 220 case Decl::Record: { 221 const RecordDecl* RD = cast<RecordDecl>(DC); 222 if (RD->isCompleteDefinition()) 223 Out << "[struct] "; 224 else 225 Out << "<struct> "; 226 Out << *RD; 227 break; 228 } 229 case Decl::CXXRecord: { 230 const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC); 231 if (RD->isCompleteDefinition()) 232 Out << "[class] "; 233 else 234 Out << "<class> "; 235 Out << *RD << ' ' << DC; 236 break; 237 } 238 case Decl::ObjCMethod: 239 Out << "[objc method]"; 240 break; 241 case Decl::ObjCInterface: 242 Out << "[objc interface]"; 243 break; 244 case Decl::ObjCCategory: 245 Out << "[objc category]"; 246 break; 247 case Decl::ObjCProtocol: 248 Out << "[objc protocol]"; 249 break; 250 case Decl::ObjCImplementation: 251 Out << "[objc implementation]"; 252 break; 253 case Decl::ObjCCategoryImpl: 254 Out << "[objc categoryimpl]"; 255 break; 256 case Decl::LinkageSpec: 257 Out << "[linkage spec]"; 258 break; 259 case Decl::Block: 260 Out << "[block]"; 261 break; 262 case Decl::Function: { 263 const FunctionDecl* FD = cast<FunctionDecl>(DC); 264 if (FD->doesThisDeclarationHaveABody()) 265 Out << "[function] "; 266 else 267 Out << "<function> "; 268 Out << *FD; 269 // Print the parameters. 270 Out << "("; 271 bool PrintComma = false; 272 for (auto I : FD->params()) { 273 if (PrintComma) 274 Out << ", "; 275 else 276 PrintComma = true; 277 Out << *I; 278 } 279 Out << ")"; 280 break; 281 } 282 case Decl::CXXMethod: { 283 const CXXMethodDecl* D = cast<CXXMethodDecl>(DC); 284 if (D->isOutOfLine()) 285 Out << "[c++ method] "; 286 else if (D->isImplicit()) 287 Out << "(c++ method) "; 288 else 289 Out << "<c++ method> "; 290 Out << *D; 291 // Print the parameters. 292 Out << "("; 293 bool PrintComma = false; 294 for (FunctionDecl::param_const_iterator I = D->param_begin(), 295 E = D->param_end(); I != E; ++I) { 296 if (PrintComma) 297 Out << ", "; 298 else 299 PrintComma = true; 300 Out << **I; 301 } 302 Out << ")"; 303 304 // Check the semantic DeclContext. 305 const DeclContext* SemaDC = D->getDeclContext(); 306 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 307 if (SemaDC != LexicalDC) 308 Out << " [[" << SemaDC << "]]"; 309 310 break; 311 } 312 case Decl::CXXConstructor: { 313 const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC); 314 if (D->isOutOfLine()) 315 Out << "[c++ ctor] "; 316 else if (D->isImplicit()) 317 Out << "(c++ ctor) "; 318 else 319 Out << "<c++ ctor> "; 320 Out << *D; 321 // Print the parameters. 322 Out << "("; 323 bool PrintComma = false; 324 for (FunctionDecl::param_const_iterator I = D->param_begin(), 325 E = D->param_end(); I != E; ++I) { 326 if (PrintComma) 327 Out << ", "; 328 else 329 PrintComma = true; 330 Out << **I; 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