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