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