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