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