Home | History | Annotate | Download | only in Frontend
      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     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 
     50 ASTConsumer *clang::CreateASTPrinter(raw_ostream* out) {
     51   return new ASTPrinter(out);
     52 }
     53 
     54 ASTConsumer *clang::CreateASTDumper() {
     55   return new ASTPrinter(0, true);
     56 }
     57 
     58 //===----------------------------------------------------------------------===//
     59 /// ASTViewer - AST Visualization
     60 
     61 namespace {
     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 
     79 void 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 
     92 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
     93 
     94 //===----------------------------------------------------------------------===//
     95 /// DeclContextPrinter - Decl and DeclContext Visualization
     96 
     97 namespace {
     98 
     99 class DeclContextPrinter : public ASTConsumer {
    100   raw_ostream& Out;
    101 public:
    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 
    112 void 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 }
    400 ASTConsumer *clang::CreateDeclContextPrinter() {
    401   return new DeclContextPrinter();
    402 }
    403 
    404 //===----------------------------------------------------------------------===//
    405 /// ASTDumperXML - In-depth XML dumping.
    406 
    407 namespace {
    408 class ASTDumpXML : public ASTConsumer {
    409   raw_ostream &OS;
    410 
    411 public:
    412   ASTDumpXML(raw_ostream &OS) : OS(OS) {}
    413 
    414   void HandleTranslationUnit(ASTContext &C) {
    415     C.getTranslationUnitDecl()->dumpXML(OS);
    416   }
    417 };
    418 }
    419 
    420 ASTConsumer *clang::CreateASTDumperXML(raw_ostream &OS) {
    421   return new ASTDumpXML(OS);
    422 }
    423