zcov: / lib/Frontend/ASTConsumers.cpp


Files: 1 Branches Taken: 50.8% 92 / 181
Generated: 2010-02-10 01:31 Branches Executed: 75.7% 137 / 181
Line Coverage: 67.4% 215 / 319


Programs: 1 Runs 2897


       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/Frontend/DocumentXML.h"
      16                 : #include "clang/Frontend/PathDiagnosticClients.h"
      17                 : #include "clang/Basic/Diagnostic.h"
      18                 : #include "clang/Basic/SourceManager.h"
      19                 : #include "clang/Basic/FileManager.h"
      20                 : #include "clang/AST/AST.h"
      21                 : #include "clang/AST/ASTConsumer.h"
      22                 : #include "clang/AST/ASTContext.h"
      23                 : #include "clang/AST/RecordLayout.h"
      24                 : #include "clang/AST/PrettyPrinter.h"
      25                 : #include "clang/CodeGen/ModuleBuilder.h"
      26                 : #include "llvm/Module.h"
      27                 : #include "llvm/Support/Format.h"
      28                 : #include "llvm/Support/Timer.h"
      29                 : #include "llvm/Support/raw_ostream.h"
      30                 : #include "llvm/System/Path.h"
      31                 : using namespace clang;
      32                 : 
      33                 : //===----------------------------------------------------------------------===//
      34                 : /// ASTPrinter - Pretty-printer and dumper of ASTs
      35                 : 
      36                 : namespace {
                       22: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
      37               22:   class ASTPrinter : public ASTConsumer {
      38                 :     llvm::raw_ostream &Out;
      39                 :     bool Dump;
      40                 : 
      41                 :   public:
      42               22:     ASTPrinter(llvm::raw_ostream* o = NULL, bool Dump = false)
                        5: branch 1 taken
                       17: branch 2 taken
      43               22:       : Out(o? *o : llvm::errs()), Dump(Dump) { }
      44                 : 
      45               22:     virtual void HandleTranslationUnit(ASTContext &Context) {
      46               22:       PrintingPolicy Policy = Context.PrintingPolicy;
      47               22:       Policy.Dump = Dump;
      48               22:       Context.getTranslationUnitDecl()->print(Out, Policy);
      49               22:     }
      50                 :   };
      51                 : } // end anonymous namespace
      52                 : 
      53               17: ASTConsumer *clang::CreateASTPrinter(llvm::raw_ostream* out) {
      54               17:   return new ASTPrinter(out);
      55                 : }
      56                 : 
      57                 : //===----------------------------------------------------------------------===//
      58                 : /// ASTPrinterXML - XML-printer of ASTs
      59                 : 
      60                 : namespace {
                        1: branch 2 taken
                        0: branch 3 not taken
                        0: branch 7 not taken
                        0: branch 8 not taken
      61                1:   class ASTPrinterXML : public ASTConsumer {
      62                 :     DocumentXML         Doc;
      63                 : 
      64                 :   public:
      65                1:     ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {}
      66                 : 
      67                1:     void Initialize(ASTContext &Context) {
      68                1:       Doc.initialize(Context);
      69                1:     }
      70                 : 
      71                1:     virtual void HandleTranslationUnit(ASTContext &Ctx) {
      72                1:       Doc.addSubNode("TranslationUnit");
                       31: branch 2 taken
                        1: branch 3 taken
      73               32:       for (DeclContext::decl_iterator
      74                1:              D = Ctx.getTranslationUnitDecl()->decls_begin(),
      75                1:              DEnd = Ctx.getTranslationUnitDecl()->decls_end();
      76                 :            D != DEnd;
      77                 :            ++D)
      78               31:         Doc.PrintDecl(*D);
      79                1:       Doc.toParent();
      80                1:       Doc.finalize();
      81                1:     }
      82                 :   };
      83                 : } // end anonymous namespace
      84                 : 
      85                 : 
      86                1: ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) {
                        0: branch 0 not taken
                        1: branch 1 taken
      87                1:   return new ASTPrinterXML(out ? *out : llvm::outs());
      88                 : }
      89                 : 
      90                5: ASTConsumer *clang::CreateASTDumper() {
      91                5:   return new ASTPrinter(0, true);
      92                 : }
      93                 : 
      94                 : //===----------------------------------------------------------------------===//
      95                 : /// ASTViewer - AST Visualization
      96                 : 
      97                 : namespace {
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 6 not taken
                        0: branch 7 not taken
      98                0:   class ASTViewer : public ASTConsumer {
      99                 :     ASTContext *Context;
     100                 :   public:
     101                0:     void Initialize(ASTContext &Context) {
     102                0:       this->Context = &Context;
     103                0:     }
     104                 : 
     105                0:     virtual void HandleTopLevelDecl(DeclGroupRef D) {
                        0: branch 2 not taken
                        0: branch 3 not taken
     106                0:       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
     107                0:         HandleTopLevelSingleDecl(*I);
     108                0:     }
     109                 : 
     110                 :     void HandleTopLevelSingleDecl(Decl *D);
     111                 :   };
     112                 : }
     113                 : 
     114                0: void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
                        0: branch 1 not taken
                        0: branch 2 not taken
     115                0:   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     116                0:     FD->print(llvm::errs());
     117                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
     118                0:     if (Stmt *Body = FD->getBody()) {
     119                0:       llvm::errs() << '\n';
     120                0:       Body->viewAST();
     121                0:       llvm::errs() << '\n';
     122                 :     }
     123                0:     return;
     124                 :   }
     125                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
     126                0:   if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
     127                0:     MD->print(llvm::errs());
     128                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
     129                0:     if (MD->getBody()) {
     130                0:       llvm::errs() << '\n';
     131                0:       MD->getBody()->viewAST();
     132                0:       llvm::errs() << '\n';
     133                 :     }
     134                 :   }
     135                 : }
     136                 : 
     137                 : 
     138                0: ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
     139                 : 
     140                 : //===----------------------------------------------------------------------===//
     141                 : /// DeclContextPrinter - Decl and DeclContext Visualization
     142                 : 
     143                 : namespace {
     144                 : 
                        2: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     145                2: class DeclContextPrinter : public ASTConsumer {
     146                 :   llvm::raw_ostream& Out;
     147                 : public:
     148                2:   DeclContextPrinter() : Out(llvm::errs()) {}
     149                 : 
     150                2:   void HandleTranslationUnit(ASTContext &C) {
                        2: branch 1 taken
                        0: branch 2 not taken
     151                2:     PrintDeclContext(C.getTranslationUnitDecl(), 4);
     152                2:   }
     153                 : 
     154                 :   void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
     155                 : };
     156                 : }  // end anonymous namespace
     157                 : 
     158                 : void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
     159               47:                                           unsigned Indentation) {
     160                 :   // Print DeclContext name.
                        2: branch 1 taken
                        2: branch 2 taken
                        1: branch 3 taken
                        7: branch 4 taken
                        6: branch 5 taken
                        0: branch 6 not taken
                        0: branch 7 not taken
                        0: branch 8 not taken
                        0: branch 9 not taken
                        0: branch 10 not taken
                        0: branch 11 not taken
                        0: branch 12 not taken
                        0: branch 13 not taken
                       17: branch 14 taken
                        3: branch 15 taken
                        6: branch 16 taken
                        3: branch 17 taken
                        0: branch 18 not taken
                        0: branch 19 not taken
     161               47:   switch (DC->getDeclKind()) {
     162                 :   case Decl::TranslationUnit:
     163                2:     Out << "[translation unit] " << DC;
     164                2:     break;
     165                 :   case Decl::Namespace: {
     166                2:     Out << "[namespace] ";
     167                2:     const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
     168                2:     Out << ND->getNameAsString();
     169                2:     break;
     170                 :   }
     171                 :   case Decl::Enum: {
     172                1:     const EnumDecl* ED = cast<EnumDecl>(DC);
                        1: branch 1 taken
                        0: branch 2 not taken
     173                1:     if (ED->isDefinition())
     174                1:       Out << "[enum] ";
     175                 :     else
     176                0:       Out << "<enum> ";
     177                1:     Out << ED->getNameAsString();
     178                1:     break;
     179                 :   }
     180                 :   case Decl::Record: {
     181                7:     const RecordDecl* RD = cast<RecordDecl>(DC);
                        6: branch 1 taken
                        1: branch 2 taken
     182                7:     if (RD->isDefinition())
     183                6:       Out << "[struct] ";
     184                 :     else
     185                1:       Out << "<struct> ";
     186                7:     Out << RD->getNameAsString();
     187                7:     break;
     188                 :   }
     189                 :   case Decl::CXXRecord: {
     190                6:     const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
                        3: branch 1 taken
                        3: branch 2 taken
     191                6:     if (RD->isDefinition())
     192                3:       Out << "[class] ";
     193                 :     else
     194                3:       Out << "<class> ";
     195                6:     Out << RD->getNameAsString() << " " << DC;
     196                6:     break;
     197                 :   }
     198                 :   case Decl::ObjCMethod:
     199                0:     Out << "[objc method]";
     200                0:     break;
     201                 :   case Decl::ObjCInterface:
     202                0:     Out << "[objc interface]";
     203                0:     break;
     204                 :   case Decl::ObjCCategory:
     205                0:     Out << "[objc category]";
     206                0:     break;
     207                 :   case Decl::ObjCProtocol:
     208                0:     Out << "[objc protocol]";
     209                0:     break;
     210                 :   case Decl::ObjCImplementation:
     211                0:     Out << "[objc implementation]";
     212                0:     break;
     213                 :   case Decl::ObjCCategoryImpl:
     214                0:     Out << "[objc categoryimpl]";
     215                0:     break;
     216                 :   case Decl::LinkageSpec:
     217                0:     Out << "[linkage spec]";
     218                0:     break;
     219                 :   case Decl::Block:
     220                0:     Out << "[block]";
     221                0:     break;
     222                 :   case Decl::Function: {
     223               17:     const FunctionDecl* FD = cast<FunctionDecl>(DC);
                       11: branch 1 taken
                        6: branch 2 taken
     224               17:     if (FD->isThisDeclarationADefinition())
     225               11:       Out << "[function] ";
     226                 :     else
     227                6:       Out << "<function> ";
     228               17:     Out << FD->getNameAsString();
     229                 :     // Print the parameters.
     230               17:     Out << "(";
     231               17:     bool PrintComma = false;
                       17: branch 1 taken
                       17: branch 2 taken
     232               51:     for (FunctionDecl::param_const_iterator I = FD->param_begin(),
     233               17:            E = FD->param_end(); I != E; ++I) {
                        5: branch 0 taken
                       12: branch 1 taken
     234               17:       if (PrintComma)
     235                5:         Out << ", ";
     236                 :       else
     237               12:         PrintComma = true;
     238               17:       Out << (*I)->getNameAsString();
     239                 :     }
     240               17:     Out << ")";
     241               17:     break;
     242                 :   }
     243                 :   case Decl::CXXMethod: {
     244                3:     const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
                        0: branch 1 not taken
                        3: branch 2 taken
     245                3:     if (D->isOutOfLine())
     246                0:       Out << "[c++ method] ";
                        3: branch 1 taken
                        0: branch 2 not taken
     247                3:     else if (D->isImplicit())
     248                3:       Out << "(c++ method) ";
     249                 :     else
     250                0:       Out << "<c++ method> ";
     251                3:     Out << D->getNameAsString();
     252                 :     // Print the parameters.
     253                3:     Out << "(";
     254                3:     bool PrintComma = false;
                        3: branch 1 taken
                        3: branch 2 taken
     255                9:     for (FunctionDecl::param_const_iterator I = D->param_begin(),
     256                3:            E = D->param_end(); I != E; ++I) {
                        0: branch 0 not taken
                        3: branch 1 taken
     257                3:       if (PrintComma)
     258                0:         Out << ", ";
     259                 :       else
     260                3:         PrintComma = true;
     261                3:       Out << (*I)->getNameAsString();
     262                 :     }
     263                3:     Out << ")";
     264                 : 
     265                 :     // Check the semantic DeclContext.
     266                3:     const DeclContext* SemaDC = D->getDeclContext();
     267                3:     const DeclContext* LexicalDC = D->getLexicalDeclContext();
                        0: branch 0 not taken
                        3: branch 1 taken
     268                3:     if (SemaDC != LexicalDC)
     269                0:       Out << " [[" << SemaDC << "]]";
     270                 : 
     271                3:     break;
     272                 :   }
     273                 :   case Decl::CXXConstructor: {
     274                6:     const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
                        0: branch 1 not taken
                        6: branch 2 taken
     275                6:     if (D->isOutOfLine())
     276                0:       Out << "[c++ ctor] ";
                        6: branch 1 taken
                        0: branch 2 not taken
     277                6:     else if (D->isImplicit())
     278                6:       Out << "(c++ ctor) ";
     279                 :     else
     280                0:       Out << "<c++ ctor> ";
     281                6:     Out << D->getNameAsString();
     282                 :     // Print the parameters.
     283                6:     Out << "(";
     284                6:     bool PrintComma = false;
                        3: branch 1 taken
                        6: branch 2 taken
     285               15:     for (FunctionDecl::param_const_iterator I = D->param_begin(),
     286                6:            E = D->param_end(); I != E; ++I) {
                        0: branch 0 not taken
                        3: branch 1 taken
     287                3:       if (PrintComma)
     288                0:         Out << ", ";
     289                 :       else
     290                3:         PrintComma = true;
     291                3:       Out << (*I)->getNameAsString();
     292                 :     }
     293                6:     Out << ")";
     294                 : 
     295                 :     // Check the semantic DC.
     296                6:     const DeclContext* SemaDC = D->getDeclContext();
     297                6:     const DeclContext* LexicalDC = D->getLexicalDeclContext();
                        0: branch 0 not taken
                        6: branch 1 taken
     298                6:     if (SemaDC != LexicalDC)
     299                0:       Out << " [[" << SemaDC << "]]";
     300                6:     break;
     301                 :   }
     302                 :   case Decl::CXXDestructor: {
     303                3:     const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
                        0: branch 1 not taken
                        3: branch 2 taken
     304                3:     if (D->isOutOfLine())
     305                0:       Out << "[c++ dtor] ";
                        3: branch 1 taken
                        0: branch 2 not taken
     306                3:     else if (D->isImplicit())
     307                3:       Out << "(c++ dtor) ";
     308                 :     else
     309                0:       Out << "<c++ dtor> ";
     310                3:     Out << D->getNameAsString();
     311                 :     // Check the semantic DC.
     312                3:     const DeclContext* SemaDC = D->getDeclContext();
     313                3:     const DeclContext* LexicalDC = D->getLexicalDeclContext();
                        0: branch 0 not taken
                        3: branch 1 taken
     314                3:     if (SemaDC != LexicalDC)
     315                0:       Out << " [[" << SemaDC << "]]";
     316                3:     break;
     317                 :   }
     318                 :   case Decl::CXXConversion: {
     319                0:     const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
                        0: branch 1 not taken
                        0: branch 2 not taken
     320                0:     if (D->isOutOfLine())
     321                0:       Out << "[c++ conversion] ";
                        0: branch 1 not taken
                        0: branch 2 not taken
     322                0:     else if (D->isImplicit())
     323                0:       Out << "(c++ conversion) ";
     324                 :     else
     325                0:       Out << "<c++ conversion> ";
     326                0:     Out << D->getNameAsString();
     327                 :     // Check the semantic DC.
     328                0:     const DeclContext* SemaDC = D->getDeclContext();
     329                0:     const DeclContext* LexicalDC = D->getLexicalDeclContext();
                        0: branch 0 not taken
                        0: branch 1 not taken
     330                0:     if (SemaDC != LexicalDC)
     331                0:       Out << " [[" << SemaDC << "]]";
     332                0:     break;
     333                 :   }
     334                 : 
     335                 :   default:
     336                0:     assert(0 && "a decl that inherits DeclContext isn't handled");
     337                 :   }
     338                 : 
     339               47:   Out << "\n";
     340                 : 
     341                 :   // Print decls in the DeclContext.
                      139: branch 4 taken
                       47: branch 5 taken
     342              186:   for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
     343                 :        I != E; ++I) {
                      766: branch 0 taken
                      139: branch 1 taken
     344              905:     for (unsigned i = 0; i < Indentation; ++i)
     345              766:       Out << "  ";
     346                 : 
     347              139:     Decl::Kind DK = I->getKind();
                       45: branch 0 taken
                        8: branch 1 taken
                        8: branch 2 taken
                        1: branch 3 taken
                       63: branch 4 taken
                        0: branch 5 not taken
                       10: branch 6 taken
                        0: branch 7 not taken
                        0: branch 8 not taken
                        1: branch 9 taken
                        2: branch 10 taken
                        1: branch 11 taken
                        0: branch 12 not taken
                        0: branch 13 not taken
     348              139:     switch (DK) {
     349                 :     case Decl::Namespace:
     350                 :     case Decl::Enum:
     351                 :     case Decl::Record:
     352                 :     case Decl::CXXRecord:
     353                 :     case Decl::ObjCMethod:
     354                 :     case Decl::ObjCInterface:
     355                 :     case Decl::ObjCCategory:
     356                 :     case Decl::ObjCProtocol:
     357                 :     case Decl::ObjCImplementation:
     358                 :     case Decl::ObjCCategoryImpl:
     359                 :     case Decl::LinkageSpec:
     360                 :     case Decl::Block:
     361                 :     case Decl::Function:
     362                 :     case Decl::CXXMethod:
     363                 :     case Decl::CXXConstructor:
     364                 :     case Decl::CXXDestructor:
     365                 :     case Decl::CXXConversion:
     366                 :     {
     367               45:       DeclContext* DC = cast<DeclContext>(*I);
     368               45:       PrintDeclContext(DC, Indentation+2);
     369               45:       break;
     370                 :     }
     371                 :     case Decl::Field: {
     372                8:       FieldDecl* FD = cast<FieldDecl>(*I);
     373                8:       Out << "<field> " << FD->getNameAsString() << "\n";
     374                8:       break;
     375                 :     }
     376                 :     case Decl::Typedef: {
     377                8:       TypedefDecl* TD = cast<TypedefDecl>(*I);
     378                8:       Out << "<typedef> " << TD->getNameAsString() << "\n";
     379                8:       break;
     380                 :     }
     381                 :     case Decl::EnumConstant: {
     382                1:       EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
     383                1:       Out << "<enum constant> " << ECD->getNameAsString() << "\n";
     384                1:       break;
     385                 :     }
     386                 :     case Decl::Var: {
     387               63:       VarDecl* VD = cast<VarDecl>(*I);
     388               63:       Out << "<var> " << VD->getNameAsString() << "\n";
     389               63:       break;
     390                 :     }
     391                 :     case Decl::ImplicitParam: {
     392                0:       ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
     393                0:       Out << "<implicit parameter> " << IPD->getNameAsString() << "\n";
     394                0:       break;
     395                 :     }
     396                 :     case Decl::ParmVar: {
     397               10:       ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
     398               10:       Out << "<parameter> " << PVD->getNameAsString() << "\n";
     399               10:       break;
     400                 :     }
     401                 :     case Decl::ObjCProperty: {
     402                0:       ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
     403                0:       Out << "<objc property> " << OPD->getNameAsString() << "\n";
     404                0:       break;
     405                 :     }
     406                 :     case Decl::FunctionTemplate: {
     407                0:       FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
     408                0:       Out << "<function template> " << FTD->getNameAsString() << "\n";
     409                0:       break;
     410                 :     }
     411                 :     case Decl::FileScopeAsm: {
     412                1:       Out << "<file-scope asm>\n";
     413                1:       break;
     414                 :     }
     415                 :     case Decl::UsingDirective: {
     416                2:       Out << "<using directive>\n";
     417                2:       break;
     418                 :     }
     419                 :     case Decl::NamespaceAlias: {
     420                1:       NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
     421                1:       Out << "<namespace alias> " << NAD->getNameAsString() << "\n";
     422                1:       break;
     423                 :     }
     424                 :     case Decl::ClassTemplate: {
     425                0:       ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
     426                0:       Out << "<class template> " << CTD->getNameAsString() << '\n';
     427                0:       break;
     428                 :     }
     429                 :     default:
     430                0:       Out << "DeclKind: " << DK << '"' << I->getDeclKindName() << "\"\n";
     431                0:       assert(0 && "decl unhandled");
     432                 :     }
     433                 :   }
     434               47: }
     435                2: ASTConsumer *clang::CreateDeclContextPrinter() {
     436                2:   return new DeclContextPrinter();
     437                 : }
     438                 : 
     439                 : //===----------------------------------------------------------------------===//
     440                 : /// RecordLayoutDumper - C++ Record Layout Dumping.
     441                 : namespace {
                        1: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     442                1: class RecordLayoutDumper : public ASTConsumer {
     443                 :   llvm::raw_ostream& Out;
     444                 :   
     445                6:   void PrintOffset(uint64_t Offset, unsigned IndentLevel) {
     446                6:     Out << llvm::format("%4d | ", Offset);
                        6: branch 1 taken
                        6: branch 2 taken
     447                6:     for (unsigned I = 0; I < IndentLevel * 2; ++I) Out << ' ';
     448                6:   }
     449                 :   
     450                 :   void DumpRecordLayoutOffsets(const CXXRecordDecl *RD, ASTContext &C,
     451                 :                                uint64_t Offset,
     452                 :                                unsigned IndentLevel, const char* Description,
     453                5:                                bool IncludeVirtualBases) {
     454                5:     const ASTRecordLayout &Info = C.getASTRecordLayout(RD);
     455                 : 
     456                5:     PrintOffset(Offset, IndentLevel);
     457                5:     Out << C.getTypeDeclType((CXXRecordDecl *)RD).getAsString();
                        2: branch 0 taken
                        3: branch 1 taken
     458                5:     if (Description)
     459                2:       Out << ' ' << Description;
                        4: branch 1 taken
                        1: branch 2 taken
     460                5:     if (RD->isEmpty())
     461                4:       Out << " (empty)";
     462                5:     Out << '\n';
     463                 :     
     464                5:     IndentLevel++;
     465                 :     
     466                5:     const CXXRecordDecl *PrimaryBase = Info.getPrimaryBase();
     467                 :     
     468                 :     // Vtable pointer.
                        1: branch 1 taken
                        4: branch 2 taken
                        1: branch 3 taken
                        0: branch 4 not taken
                        1: branch 5 taken
                        4: branch 6 taken
     469                5:     if (RD->isDynamicClass() && !PrimaryBase) {
     470                1:       PrintOffset(Offset, IndentLevel);
     471                1:       Out << '(' << RD->getNameAsString() << " vtable pointer)\n";
     472                 :     }
     473                 :     // Dump (non-virtual) bases
                        2: branch 1 taken
                        5: branch 2 taken
     474               12:     for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
     475                5:          E = RD->bases_end(); I != E; ++I) {
     476                 :       assert(!I->getType()->isDependentType() &&
                        2: branch 3 taken
                        0: branch 4 not taken
     477                2:              "Cannot layout class with dependent bases.");
                        1: branch 1 taken
                        1: branch 2 taken
     478                2:       if (I->isVirtual())
     479                1:         continue;
     480                 :       
     481                 :       const CXXRecordDecl *Base =
     482                1:         cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
     483                 :       
     484                1:       uint64_t BaseOffset = Offset + Info.getBaseClassOffset(Base) / 8;
     485                 :       
     486                 :       DumpRecordLayoutOffsets(Base, C, BaseOffset, IndentLevel, 
     487                 :                               Base == PrimaryBase ? "(primary base)" : "(base)",
                        0: branch 0 not taken
                        1: branch 1 taken
     488                1:                               /*IncludeVirtualBases=*/false);
     489                 :     }
     490                 :     
     491                 :     // Dump fields.
     492                5:     uint64_t FieldNo = 0;
                        0: branch 3 not taken
                        5: branch 4 taken
     493               10:     for (CXXRecordDecl::field_iterator I = RD->field_begin(),
     494                5:          E = RD->field_end(); I != E; ++I, ++FieldNo) {      
     495                0:       const FieldDecl *Field = *I;
     496                0:       uint64_t FieldOffset = Offset + Info.getFieldOffset(FieldNo) / 8;
     497                 :       
                        0: branch 3 not taken
                        0: branch 4 not taken
     498                0:       if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
                        0: branch 2 not taken
                        0: branch 3 not taken
     499                0:         if (const CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
     500                 :           DumpRecordLayoutOffsets(D, C, FieldOffset, IndentLevel, 
     501                 :                                   Field->getNameAsCString(),
     502                0:                                   /*IncludeVirtualBases=*/true);
     503                0:           continue;
     504                 :         }
     505                 :       }
     506                 :       
     507                0:       PrintOffset(FieldOffset, IndentLevel);
     508                0:       Out << Field->getType().getAsString() << ' ';
     509                0:       Out << Field->getNameAsString() << '\n';
     510                 :     }
     511                 :     
                        2: branch 0 taken
                        3: branch 1 taken
     512                5:     if (!IncludeVirtualBases)
     513                2:       return;
     514                 :     
     515                 :     // Dump virtual bases.
                        1: branch 1 taken
                        3: branch 2 taken
     516                7:     for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
     517                3:          E = RD->vbases_end(); I != E; ++I) {
                        1: branch 1 taken
                        0: branch 2 not taken
     518                1:       assert(I->isVirtual() && "Found non-virtual class!");
     519                 :       const CXXRecordDecl *VBase =
     520                1:         cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
     521                 :       
     522                1:       uint64_t VBaseOffset = Offset + Info.getVBaseClassOffset(VBase) / 8;
     523                 :       DumpRecordLayoutOffsets(VBase, C, VBaseOffset, IndentLevel, 
     524                 :                               VBase == PrimaryBase ? 
     525                 :                               "(primary virtual base)" : "(virtual base)",
                        0: branch 0 not taken
                        1: branch 1 taken
     526                1:                               /*IncludeVirtualBases=*/false);
     527                 :     }
     528                 :   }
     529                 :   
     530                 :   // FIXME: Maybe this could be useful in ASTContext.cpp.
     531                3:   void DumpRecordLayout(const CXXRecordDecl *RD, ASTContext &C) {
     532                3:     const ASTRecordLayout &Info = C.getASTRecordLayout(RD);
     533                 :     
     534                 :     DumpRecordLayoutOffsets(RD, C, 0, 0, 0, 
     535                3:                             /*IncludeVirtualBases=*/true);
     536                3:     Out << "  sizeof=" << Info.getSize() / 8;
     537                3:     Out << ", dsize=" << Info.getDataSize() / 8;
     538                3:     Out << ", align=" << Info.getAlignment() / 8 << '\n';
     539                3:     Out << "  nvsize=" << Info.getNonVirtualSize() / 8;
     540                3:     Out << ", nvalign=" << Info.getNonVirtualAlign() / 8 << '\n';
     541                3:     Out << '\n';
     542                3:   }
     543                 :   
     544                 : public:
     545                1:   RecordLayoutDumper() : Out(llvm::errs()) {}
     546                 :   
     547                1:   void HandleTranslationUnit(ASTContext &C) {
                       49: branch 4 taken
                        1: branch 5 taken
     548               50:     for (ASTContext::type_iterator I = C.types_begin(), E = C.types_end(); 
     549                 :          I != E; ++I) {
     550               49:       const RecordType *RT = dyn_cast<RecordType>(*I);
                       46: branch 0 taken
                        3: branch 1 taken
     551               49:       if (!RT)
     552               46:         continue;
     553                 :       
     554                3:       const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
                        0: branch 0 not taken
                        3: branch 1 taken
     555                3:       if (!RD)
     556                0:         continue;
     557                 :       
                        0: branch 1 not taken
                        3: branch 2 taken
     558                3:       if (RD->isImplicit())
     559                0:         continue;
     560                 : 
                        0: branch 1 not taken
                        3: branch 2 taken
     561                3:       if (RD->isDependentType())
     562                0:         continue;
     563                 :       
                        0: branch 1 not taken
                        3: branch 2 taken
     564                3:       if (RD->isInvalidDecl())
     565                0:         continue;
     566                 :       
                        0: branch 1 not taken
                        3: branch 2 taken
     567                3:       if (!RD->getDefinition(C))
     568                0:         continue;
     569                 :       
     570                 :       // FIXME: Do we really need to hard code this?
                        0: branch 3 not taken
                        3: branch 4 taken
     571                3:       if (RD->getQualifiedNameAsString() == "__va_list_tag")
     572                0:         continue;
     573                 :       
     574                3:       DumpRecordLayout(RD, C);
     575                 :    }
     576                1:   }
     577                 : };
     578                 : } // end anonymous namespace
     579                1: ASTConsumer *clang::CreateRecordLayoutDumper() {
     580                1:   return new RecordLayoutDumper();
     581                 : }
     582                 : 
     583                 : //===----------------------------------------------------------------------===//
     584                 : /// InheritanceViewer - C++ Inheritance Visualization
     585                 : 
     586                 : namespace {
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 7 not taken
                        0: branch 8 not taken
     587                0: class InheritanceViewer : public ASTConsumer {
     588                 :   const std::string clsname;
     589                 : public:
     590                0:   InheritanceViewer(const std::string& cname) : clsname(cname) {}
     591                 : 
     592                0:   void HandleTranslationUnit(ASTContext &C) {
                        0: branch 4 not taken
                        0: branch 5 not taken
     593                0:     for (ASTContext::type_iterator I=C.types_begin(),E=C.types_end(); I!=E; ++I)
                        0: branch 2 not taken
                        0: branch 3 not taken
     594                0:       if (RecordType *T = dyn_cast<RecordType>(*I)) {
                        0: branch 2 not taken
                        0: branch 3 not taken
     595                0:         if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(T->getDecl())) {
     596                 :           // FIXME: This lookup needs to be generalized to handle namespaces and
     597                 :           // (when we support them) templates.
                        0: branch 3 not taken
                        0: branch 4 not taken
     598                0:           if (D->getNameAsString() == clsname) {
     599                0:             D->viewInheritance(C);
     600                 :           }
     601                 :         }
     602                 :       }
     603                0:   }
     604                 : };
     605                 : }
     606                 : 
     607                0: ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) {
     608                0:   return new InheritanceViewer(clsname);
     609                 : }

Generated: 2010-02-10 01:31 by zcov