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" 27using namespace clang; 28 29//===----------------------------------------------------------------------===// 30/// ASTPrinter - Pretty-printer and dumper of ASTs 31 32namespace { 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 125std::unique_ptr<ASTConsumer> clang::CreateASTPrinter(raw_ostream *Out, 126 StringRef FilterString) { 127 return llvm::make_unique<ASTPrinter>(Out, /*Dump=*/false, FilterString); 128} 129 130std::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 138std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() { 139 return llvm::make_unique<ASTDeclNodeLister>(nullptr); 140} 141 142//===----------------------------------------------------------------------===// 143/// ASTViewer - AST Visualization 144 145namespace { 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 163void 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 175std::unique_ptr<ASTConsumer> clang::CreateASTViewer() { 176 return llvm::make_unique<ASTViewer>(); 177} 178 179//===----------------------------------------------------------------------===// 180/// DeclContextPrinter - Decl and DeclContext Visualization 181 182namespace { 183 184class DeclContextPrinter : public ASTConsumer { 185 raw_ostream& Out; 186public: 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 197void 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->parameters()) { 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 (ParmVarDecl *Parameter : D->parameters()) { 294 if (PrintComma) 295 Out << ", "; 296 else 297 PrintComma = true; 298 Out << *Parameter; 299 } 300 Out << ")"; 301 302 // Check the semantic DeclContext. 303 const DeclContext* SemaDC = D->getDeclContext(); 304 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 305 if (SemaDC != LexicalDC) 306 Out << " [[" << SemaDC << "]]"; 307 308 break; 309 } 310 case Decl::CXXConstructor: { 311 const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC); 312 if (D->isOutOfLine()) 313 Out << "[c++ ctor] "; 314 else if (D->isImplicit()) 315 Out << "(c++ ctor) "; 316 else 317 Out << "<c++ ctor> "; 318 Out << *D; 319 // Print the parameters. 320 Out << "("; 321 bool PrintComma = false; 322 for (ParmVarDecl *Parameter : D->parameters()) { 323 if (PrintComma) 324 Out << ", "; 325 else 326 PrintComma = true; 327 Out << *Parameter; 328 } 329 Out << ")"; 330 331 // Check the semantic DC. 332 const DeclContext* SemaDC = D->getDeclContext(); 333 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 334 if (SemaDC != LexicalDC) 335 Out << " [[" << SemaDC << "]]"; 336 break; 337 } 338 case Decl::CXXDestructor: { 339 const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC); 340 if (D->isOutOfLine()) 341 Out << "[c++ dtor] "; 342 else if (D->isImplicit()) 343 Out << "(c++ dtor) "; 344 else 345 Out << "<c++ dtor> "; 346 Out << *D; 347 // Check the semantic DC. 348 const DeclContext* SemaDC = D->getDeclContext(); 349 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 350 if (SemaDC != LexicalDC) 351 Out << " [[" << SemaDC << "]]"; 352 break; 353 } 354 case Decl::CXXConversion: { 355 const CXXConversionDecl* D = cast<CXXConversionDecl>(DC); 356 if (D->isOutOfLine()) 357 Out << "[c++ conversion] "; 358 else if (D->isImplicit()) 359 Out << "(c++ conversion) "; 360 else 361 Out << "<c++ conversion> "; 362 Out << *D; 363 // Check the semantic DC. 364 const DeclContext* SemaDC = D->getDeclContext(); 365 const DeclContext* LexicalDC = D->getLexicalDeclContext(); 366 if (SemaDC != LexicalDC) 367 Out << " [[" << SemaDC << "]]"; 368 break; 369 } 370 371 default: 372 llvm_unreachable("a decl that inherits DeclContext isn't handled"); 373 } 374 375 Out << "\n"; 376 377 // Print decls in the DeclContext. 378 for (auto *I : DC->decls()) { 379 for (unsigned i = 0; i < Indentation; ++i) 380 Out << " "; 381 382 Decl::Kind DK = I->getKind(); 383 switch (DK) { 384 case Decl::Namespace: 385 case Decl::Enum: 386 case Decl::Record: 387 case Decl::CXXRecord: 388 case Decl::ObjCMethod: 389 case Decl::ObjCInterface: 390 case Decl::ObjCCategory: 391 case Decl::ObjCProtocol: 392 case Decl::ObjCImplementation: 393 case Decl::ObjCCategoryImpl: 394 case Decl::LinkageSpec: 395 case Decl::Block: 396 case Decl::Function: 397 case Decl::CXXMethod: 398 case Decl::CXXConstructor: 399 case Decl::CXXDestructor: 400 case Decl::CXXConversion: 401 { 402 DeclContext* DC = cast<DeclContext>(I); 403 PrintDeclContext(DC, Indentation+2); 404 break; 405 } 406 case Decl::IndirectField: { 407 IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(I); 408 Out << "<IndirectField> " << *IFD << '\n'; 409 break; 410 } 411 case Decl::Label: { 412 LabelDecl *LD = cast<LabelDecl>(I); 413 Out << "<Label> " << *LD << '\n'; 414 break; 415 } 416 case Decl::Field: { 417 FieldDecl *FD = cast<FieldDecl>(I); 418 Out << "<field> " << *FD << '\n'; 419 break; 420 } 421 case Decl::Typedef: 422 case Decl::TypeAlias: { 423 TypedefNameDecl* TD = cast<TypedefNameDecl>(I); 424 Out << "<typedef> " << *TD << '\n'; 425 break; 426 } 427 case Decl::EnumConstant: { 428 EnumConstantDecl* ECD = cast<EnumConstantDecl>(I); 429 Out << "<enum constant> " << *ECD << '\n'; 430 break; 431 } 432 case Decl::Var: { 433 VarDecl* VD = cast<VarDecl>(I); 434 Out << "<var> " << *VD << '\n'; 435 break; 436 } 437 case Decl::ImplicitParam: { 438 ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(I); 439 Out << "<implicit parameter> " << *IPD << '\n'; 440 break; 441 } 442 case Decl::ParmVar: { 443 ParmVarDecl* PVD = cast<ParmVarDecl>(I); 444 Out << "<parameter> " << *PVD << '\n'; 445 break; 446 } 447 case Decl::ObjCProperty: { 448 ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(I); 449 Out << "<objc property> " << *OPD << '\n'; 450 break; 451 } 452 case Decl::FunctionTemplate: { 453 FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(I); 454 Out << "<function template> " << *FTD << '\n'; 455 break; 456 } 457 case Decl::FileScopeAsm: { 458 Out << "<file-scope asm>\n"; 459 break; 460 } 461 case Decl::UsingDirective: { 462 Out << "<using directive>\n"; 463 break; 464 } 465 case Decl::NamespaceAlias: { 466 NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(I); 467 Out << "<namespace alias> " << *NAD << '\n'; 468 break; 469 } 470 case Decl::ClassTemplate: { 471 ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(I); 472 Out << "<class template> " << *CTD << '\n'; 473 break; 474 } 475 case Decl::OMPThreadPrivate: { 476 Out << "<omp threadprivate> " << '"' << I << "\"\n"; 477 break; 478 } 479 default: 480 Out << "DeclKind: " << DK << '"' << I << "\"\n"; 481 llvm_unreachable("decl unhandled"); 482 } 483 } 484} 485std::unique_ptr<ASTConsumer> clang::CreateDeclContextPrinter() { 486 return llvm::make_unique<DeclContextPrinter>(); 487} 488