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