clang API Documentation

ASTConsumers.cpp
Go to the documentation of this file.
00001 //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // AST Consumer Implementations.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "clang/Frontend/ASTConsumers.h"
00015 #include "clang/Basic/Diagnostic.h"
00016 #include "clang/Basic/SourceManager.h"
00017 #include "clang/Basic/FileManager.h"
00018 #include "clang/AST/AST.h"
00019 #include "clang/AST/ASTConsumer.h"
00020 #include "clang/AST/ASTContext.h"
00021 #include "clang/AST/RecordLayout.h"
00022 #include "clang/AST/PrettyPrinter.h"
00023 #include "llvm/Module.h"
00024 #include "llvm/Support/Timer.h"
00025 #include "llvm/Support/raw_ostream.h"
00026 #include "llvm/Support/Path.h"
00027 using namespace clang;
00028 
00029 //===----------------------------------------------------------------------===//
00030 /// ASTPrinter - Pretty-printer and dumper of ASTs
00031 
00032 namespace {
00033   class ASTPrinter : public ASTConsumer {
00034     raw_ostream &Out;
00035     bool Dump;
00036 
00037   public:
00038     ASTPrinter(raw_ostream* o = NULL, bool Dump = false)
00039       : Out(o? *o : llvm::outs()), Dump(Dump) { }
00040 
00041     virtual void HandleTranslationUnit(ASTContext &Context) {
00042       PrintingPolicy Policy = Context.getPrintingPolicy();
00043       Policy.Dump = Dump;
00044       Context.getTranslationUnitDecl()->print(Out, Policy, /*Indentation=*/0,
00045                                               /*PrintInstantiation=*/true);
00046     }
00047   };
00048 } // end anonymous namespace
00049 
00050 ASTConsumer *clang::CreateASTPrinter(raw_ostream* out) {
00051   return new ASTPrinter(out);
00052 }
00053 
00054 ASTConsumer *clang::CreateASTDumper() {
00055   return new ASTPrinter(0, true);
00056 }
00057 
00058 //===----------------------------------------------------------------------===//
00059 /// ASTViewer - AST Visualization
00060 
00061 namespace {
00062   class ASTViewer : public ASTConsumer {
00063     ASTContext *Context;
00064   public:
00065     void Initialize(ASTContext &Context) {
00066       this->Context = &Context;
00067     }
00068 
00069     virtual bool HandleTopLevelDecl(DeclGroupRef D) {
00070       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
00071         HandleTopLevelSingleDecl(*I);
00072       return true;
00073     }
00074 
00075     void HandleTopLevelSingleDecl(Decl *D);
00076   };
00077 }
00078 
00079 void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
00080   if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
00081     D->print(llvm::errs());
00082   
00083     if (Stmt *Body = D->getBody()) {
00084       llvm::errs() << '\n';
00085       Body->viewAST();
00086       llvm::errs() << '\n';
00087     }
00088   }
00089 }
00090 
00091 
00092 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
00093 
00094 //===----------------------------------------------------------------------===//
00095 /// DeclContextPrinter - Decl and DeclContext Visualization
00096 
00097 namespace {
00098 
00099 class DeclContextPrinter : public ASTConsumer {
00100   raw_ostream& Out;
00101 public:
00102   DeclContextPrinter() : Out(llvm::errs()) {}
00103 
00104   void HandleTranslationUnit(ASTContext &C) {
00105     PrintDeclContext(C.getTranslationUnitDecl(), 4);
00106   }
00107 
00108   void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
00109 };
00110 }  // end anonymous namespace
00111 
00112 void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
00113                                           unsigned Indentation) {
00114   // Print DeclContext name.
00115   switch (DC->getDeclKind()) {
00116   case Decl::TranslationUnit:
00117     Out << "[translation unit] " << DC;
00118     break;
00119   case Decl::Namespace: {
00120     Out << "[namespace] ";
00121     const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
00122     Out << *ND;
00123     break;
00124   }
00125   case Decl::Enum: {
00126     const EnumDecl* ED = cast<EnumDecl>(DC);
00127     if (ED->isCompleteDefinition())
00128       Out << "[enum] ";
00129     else
00130       Out << "<enum> ";
00131     Out << *ED;
00132     break;
00133   }
00134   case Decl::Record: {
00135     const RecordDecl* RD = cast<RecordDecl>(DC);
00136     if (RD->isCompleteDefinition())
00137       Out << "[struct] ";
00138     else
00139       Out << "<struct> ";
00140     Out << *RD;
00141     break;
00142   }
00143   case Decl::CXXRecord: {
00144     const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
00145     if (RD->isCompleteDefinition())
00146       Out << "[class] ";
00147     else
00148       Out << "<class> ";
00149     Out << *RD << ' ' << DC;
00150     break;
00151   }
00152   case Decl::ObjCMethod:
00153     Out << "[objc method]";
00154     break;
00155   case Decl::ObjCInterface:
00156     Out << "[objc interface]";
00157     break;
00158   case Decl::ObjCCategory:
00159     Out << "[objc category]";
00160     break;
00161   case Decl::ObjCProtocol:
00162     Out << "[objc protocol]";
00163     break;
00164   case Decl::ObjCImplementation:
00165     Out << "[objc implementation]";
00166     break;
00167   case Decl::ObjCCategoryImpl:
00168     Out << "[objc categoryimpl]";
00169     break;
00170   case Decl::LinkageSpec:
00171     Out << "[linkage spec]";
00172     break;
00173   case Decl::Block:
00174     Out << "[block]";
00175     break;
00176   case Decl::Function: {
00177     const FunctionDecl* FD = cast<FunctionDecl>(DC);
00178     if (FD->doesThisDeclarationHaveABody())
00179       Out << "[function] ";
00180     else
00181       Out << "<function> ";
00182     Out << *FD;
00183     // Print the parameters.
00184     Out << "(";
00185     bool PrintComma = false;
00186     for (FunctionDecl::param_const_iterator I = FD->param_begin(),
00187            E = FD->param_end(); I != E; ++I) {
00188       if (PrintComma)
00189         Out << ", ";
00190       else
00191         PrintComma = true;
00192       Out << **I;
00193     }
00194     Out << ")";
00195     break;
00196   }
00197   case Decl::CXXMethod: {
00198     const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
00199     if (D->isOutOfLine())
00200       Out << "[c++ method] ";
00201     else if (D->isImplicit())
00202       Out << "(c++ method) ";
00203     else
00204       Out << "<c++ method> ";
00205     Out << *D;
00206     // Print the parameters.
00207     Out << "(";
00208     bool PrintComma = false;
00209     for (FunctionDecl::param_const_iterator I = D->param_begin(),
00210            E = D->param_end(); I != E; ++I) {
00211       if (PrintComma)
00212         Out << ", ";
00213       else
00214         PrintComma = true;
00215       Out << **I;
00216     }
00217     Out << ")";
00218 
00219     // Check the semantic DeclContext.
00220     const DeclContext* SemaDC = D->getDeclContext();
00221     const DeclContext* LexicalDC = D->getLexicalDeclContext();
00222     if (SemaDC != LexicalDC)
00223       Out << " [[" << SemaDC << "]]";
00224 
00225     break;
00226   }
00227   case Decl::CXXConstructor: {
00228     const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
00229     if (D->isOutOfLine())
00230       Out << "[c++ ctor] ";
00231     else if (D->isImplicit())
00232       Out << "(c++ ctor) ";
00233     else
00234       Out << "<c++ ctor> ";
00235     Out << *D;
00236     // Print the parameters.
00237     Out << "(";
00238     bool PrintComma = false;
00239     for (FunctionDecl::param_const_iterator I = D->param_begin(),
00240            E = D->param_end(); I != E; ++I) {
00241       if (PrintComma)
00242         Out << ", ";
00243       else
00244         PrintComma = true;
00245       Out << **I;
00246     }
00247     Out << ")";
00248 
00249     // Check the semantic DC.
00250     const DeclContext* SemaDC = D->getDeclContext();
00251     const DeclContext* LexicalDC = D->getLexicalDeclContext();
00252     if (SemaDC != LexicalDC)
00253       Out << " [[" << SemaDC << "]]";
00254     break;
00255   }
00256   case Decl::CXXDestructor: {
00257     const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
00258     if (D->isOutOfLine())
00259       Out << "[c++ dtor] ";
00260     else if (D->isImplicit())
00261       Out << "(c++ dtor) ";
00262     else
00263       Out << "<c++ dtor> ";
00264     Out << *D;
00265     // Check the semantic DC.
00266     const DeclContext* SemaDC = D->getDeclContext();
00267     const DeclContext* LexicalDC = D->getLexicalDeclContext();
00268     if (SemaDC != LexicalDC)
00269       Out << " [[" << SemaDC << "]]";
00270     break;
00271   }
00272   case Decl::CXXConversion: {
00273     const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
00274     if (D->isOutOfLine())
00275       Out << "[c++ conversion] ";
00276     else if (D->isImplicit())
00277       Out << "(c++ conversion) ";
00278     else
00279       Out << "<c++ conversion> ";
00280     Out << *D;
00281     // Check the semantic DC.
00282     const DeclContext* SemaDC = D->getDeclContext();
00283     const DeclContext* LexicalDC = D->getLexicalDeclContext();
00284     if (SemaDC != LexicalDC)
00285       Out << " [[" << SemaDC << "]]";
00286     break;
00287   }
00288 
00289   default:
00290     llvm_unreachable("a decl that inherits DeclContext isn't handled");
00291   }
00292 
00293   Out << "\n";
00294 
00295   // Print decls in the DeclContext.
00296   for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
00297        I != E; ++I) {
00298     for (unsigned i = 0; i < Indentation; ++i)
00299       Out << "  ";
00300 
00301     Decl::Kind DK = I->getKind();
00302     switch (DK) {
00303     case Decl::Namespace:
00304     case Decl::Enum:
00305     case Decl::Record:
00306     case Decl::CXXRecord:
00307     case Decl::ObjCMethod:
00308     case Decl::ObjCInterface:
00309     case Decl::ObjCCategory:
00310     case Decl::ObjCProtocol:
00311     case Decl::ObjCImplementation:
00312     case Decl::ObjCCategoryImpl:
00313     case Decl::LinkageSpec:
00314     case Decl::Block:
00315     case Decl::Function:
00316     case Decl::CXXMethod:
00317     case Decl::CXXConstructor:
00318     case Decl::CXXDestructor:
00319     case Decl::CXXConversion:
00320     {
00321       DeclContext* DC = cast<DeclContext>(*I);
00322       PrintDeclContext(DC, Indentation+2);
00323       break;
00324     }
00325     case Decl::IndirectField: {
00326       IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(*I);
00327       Out << "<IndirectField> " << *IFD << '\n';
00328       break;
00329     }
00330     case Decl::Label: {
00331       LabelDecl *LD = cast<LabelDecl>(*I);
00332       Out << "<Label> " << *LD << '\n';
00333       break;
00334     }
00335     case Decl::Field: {
00336       FieldDecl *FD = cast<FieldDecl>(*I);
00337       Out << "<field> " << *FD << '\n';
00338       break;
00339     }
00340     case Decl::Typedef:
00341     case Decl::TypeAlias: {
00342       TypedefNameDecl* TD = cast<TypedefNameDecl>(*I);
00343       Out << "<typedef> " << *TD << '\n';
00344       break;
00345     }
00346     case Decl::EnumConstant: {
00347       EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
00348       Out << "<enum constant> " << *ECD << '\n';
00349       break;
00350     }
00351     case Decl::Var: {
00352       VarDecl* VD = cast<VarDecl>(*I);
00353       Out << "<var> " << *VD << '\n';
00354       break;
00355     }
00356     case Decl::ImplicitParam: {
00357       ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
00358       Out << "<implicit parameter> " << *IPD << '\n';
00359       break;
00360     }
00361     case Decl::ParmVar: {
00362       ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
00363       Out << "<parameter> " << *PVD << '\n';
00364       break;
00365     }
00366     case Decl::ObjCProperty: {
00367       ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
00368       Out << "<objc property> " << *OPD << '\n';
00369       break;
00370     }
00371     case Decl::FunctionTemplate: {
00372       FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
00373       Out << "<function template> " << *FTD << '\n';
00374       break;
00375     }
00376     case Decl::FileScopeAsm: {
00377       Out << "<file-scope asm>\n";
00378       break;
00379     }
00380     case Decl::UsingDirective: {
00381       Out << "<using directive>\n";
00382       break;
00383     }
00384     case Decl::NamespaceAlias: {
00385       NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
00386       Out << "<namespace alias> " << *NAD << '\n';
00387       break;
00388     }
00389     case Decl::ClassTemplate: {
00390       ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
00391       Out << "<class template> " << *CTD << '\n';
00392       break;
00393     }
00394     default:
00395       Out << "DeclKind: " << DK << '"' << *I << "\"\n";
00396       llvm_unreachable("decl unhandled");
00397     }
00398   }
00399 }
00400 ASTConsumer *clang::CreateDeclContextPrinter() {
00401   return new DeclContextPrinter();
00402 }
00403 
00404 //===----------------------------------------------------------------------===//
00405 /// ASTDumperXML - In-depth XML dumping.
00406 
00407 namespace {
00408 class ASTDumpXML : public ASTConsumer {
00409   raw_ostream &OS;
00410 
00411 public:
00412   ASTDumpXML(raw_ostream &OS) : OS(OS) {}
00413 
00414   void HandleTranslationUnit(ASTContext &C) {
00415     C.getTranslationUnitDecl()->dumpXML(OS);
00416   }  
00417 };
00418 }
00419 
00420 ASTConsumer *clang::CreateASTDumperXML(raw_ostream &OS) {
00421   return new ASTDumpXML(OS);
00422 }