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