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