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