zcov: / lib/Frontend/PCHWriterDecl.cpp


Files: 1 Branches Taken: 77.3% 102 / 132
Generated: 2010-02-10 01:31 Branches Executed: 98.5% 130 / 132
Line Coverage: 91.6% 339 / 370


Programs: 1 Runs 2897


       1                 : //===--- PCHWriterDecl.cpp - Declaration Serialization --------------------===//
       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                 : //  This file implements serialization for Declarations.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "clang/Frontend/PCHWriter.h"
      15                 : #include "clang/AST/DeclVisitor.h"
      16                 : #include "clang/AST/Expr.h"
      17                 : #include "llvm/ADT/Twine.h"
      18                 : #include "llvm/Bitcode/BitstreamWriter.h"
      19                 : #include "llvm/Support/ErrorHandling.h"
      20                 : using namespace clang;
      21                 : 
      22                 : //===----------------------------------------------------------------------===//
      23                 : // Declaration serialization
      24                 : //===----------------------------------------------------------------------===//
      25                 : 
      26                 : namespace {
      27                 :   class PCHDeclWriter : public DeclVisitor<PCHDeclWriter, void> {
      28                 : 
      29                 :     PCHWriter &Writer;
      30                 :     ASTContext &Context;
      31                 :     PCHWriter::RecordData &Record;
      32                 : 
      33                 :   public:
      34                 :     pch::DeclCode Code;
      35                 :     unsigned AbbrevToUse;
      36                 : 
      37                 :     PCHDeclWriter(PCHWriter &Writer, ASTContext &Context,
      38              602:                   PCHWriter::RecordData &Record)
      39              602:       : Writer(Writer), Context(Context), Record(Record) {
      40              602:     }
      41                 : 
      42                 :     void VisitDecl(Decl *D);
      43                 :     void VisitTranslationUnitDecl(TranslationUnitDecl *D);
      44                 :     void VisitNamedDecl(NamedDecl *D);
      45                 :     void VisitTypeDecl(TypeDecl *D);
      46                 :     void VisitTypedefDecl(TypedefDecl *D);
      47                 :     void VisitTagDecl(TagDecl *D);
      48                 :     void VisitEnumDecl(EnumDecl *D);
      49                 :     void VisitRecordDecl(RecordDecl *D);
      50                 :     void VisitValueDecl(ValueDecl *D);
      51                 :     void VisitEnumConstantDecl(EnumConstantDecl *D);
      52                 :     void VisitDeclaratorDecl(DeclaratorDecl *D);
      53                 :     void VisitFunctionDecl(FunctionDecl *D);
      54                 :     void VisitFieldDecl(FieldDecl *D);
      55                 :     void VisitVarDecl(VarDecl *D);
      56                 :     void VisitImplicitParamDecl(ImplicitParamDecl *D);
      57                 :     void VisitParmVarDecl(ParmVarDecl *D);
      58                 :     void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
      59                 :     void VisitBlockDecl(BlockDecl *D);
      60                 :     void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
      61                 :                           uint64_t VisibleOffset);
      62                 :     void VisitObjCMethodDecl(ObjCMethodDecl *D);
      63                 :     void VisitObjCContainerDecl(ObjCContainerDecl *D);
      64                 :     void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
      65                 :     void VisitObjCIvarDecl(ObjCIvarDecl *D);
      66                 :     void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
      67                 :     void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
      68                 :     void VisitObjCClassDecl(ObjCClassDecl *D);
      69                 :     void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
      70                 :     void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
      71                 :     void VisitObjCImplDecl(ObjCImplDecl *D);
      72                 :     void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
      73                 :     void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
      74                 :     void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
      75                 :     void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
      76                 :     void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
      77                 :   };
      78                 : }
      79                 : 
      80              602: void PCHDeclWriter::VisitDecl(Decl *D) {
      81              602:   Writer.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()), Record);
      82              602:   Writer.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()), Record);
      83              602:   Writer.AddSourceLocation(D->getLocation(), Record);
      84              602:   Record.push_back(D->isInvalidDecl());
      85              602:   Record.push_back(D->hasAttrs());
      86              602:   Record.push_back(D->isImplicit());
      87              602:   Record.push_back(D->isUsed());
      88              602:   Record.push_back(D->getAccess());
      89              602:   Record.push_back(D->getPCHLevel());
      90              602: }
      91                 : 
      92               44: void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
      93               44:   VisitDecl(D);
      94               44:   Code = pch::DECL_TRANSLATION_UNIT;
      95               44: }
      96                 : 
      97              550: void PCHDeclWriter::VisitNamedDecl(NamedDecl *D) {
      98              550:   VisitDecl(D);
      99              550:   Writer.AddDeclarationName(D->getDeclName(), Record);
     100              550: }
     101                 : 
     102              191: void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
     103              191:   VisitNamedDecl(D);
     104              191:   Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
     105              191: }
     106                 : 
     107              156: void PCHDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
     108              156:   VisitTypeDecl(D);
     109              156:   Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
     110              156:   Code = pch::DECL_TYPEDEF;
     111              156: }
     112                 : 
     113               35: void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
     114               35:   VisitTypeDecl(D);
     115               35:   Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
     116               35:   Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
     117               35:   Record.push_back(D->isDefinition());
     118               35:   Record.push_back(D->isDefinedInDeclarator());
     119               35:   Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);
     120               35:   Writer.AddSourceLocation(D->getRBraceLoc(), Record);
     121               35:   Writer.AddSourceLocation(D->getTagKeywordLoc(), Record);
     122               35: }
     123                 : 
     124                5: void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) {
     125                5:   VisitTagDecl(D);
     126                5:   Writer.AddTypeRef(D->getIntegerType(), Record);
     127                5:   Writer.AddTypeRef(D->getPromotionType(), Record);
     128                 :   // FIXME: C++ InstantiatedFrom
     129                5:   Code = pch::DECL_ENUM;
     130                5: }
     131                 : 
     132               30: void PCHDeclWriter::VisitRecordDecl(RecordDecl *D) {
     133               30:   VisitTagDecl(D);
     134               30:   Record.push_back(D->hasFlexibleArrayMember());
     135               30:   Record.push_back(D->isAnonymousStructOrUnion());
     136               30:   Record.push_back(D->hasObjectMember());
     137               30:   Code = pch::DECL_RECORD;
     138               30: }
     139                 : 
     140              294: void PCHDeclWriter::VisitValueDecl(ValueDecl *D) {
     141              294:   VisitNamedDecl(D);
     142              294:   Writer.AddTypeRef(D->getType(), Record);
     143              294: }
     144                 : 
     145               10: void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
     146               10:   VisitValueDecl(D);
                        2: branch 1 taken
                        8: branch 2 taken
     147               10:   Record.push_back(D->getInitExpr()? 1 : 0);
                        2: branch 1 taken
                        8: branch 2 taken
     148               10:   if (D->getInitExpr())
     149                2:     Writer.AddStmt(D->getInitExpr());
     150               10:   Writer.AddAPSInt(D->getInitVal(), Record);
     151               10:   Code = pch::DECL_ENUM_CONSTANT;
     152               10: }
     153                 : 
     154              284: void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
     155              284:   VisitValueDecl(D);
     156              284:   Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record);
     157              284: }
     158                 : 
     159               64: void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
     160               64:   VisitDeclaratorDecl(D);
     161               64:   Record.push_back(D->isThisDeclarationADefinition());
                       27: branch 1 taken
                       37: branch 2 taken
     162               64:   if (D->isThisDeclarationADefinition())
     163               27:     Writer.AddStmt(D->getBody());
     164               64:   Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
     165               64:   Record.push_back(D->getStorageClass()); // FIXME: stable encoding
     166               64:   Record.push_back(D->isInlineSpecified());
     167               64:   Record.push_back(D->isVirtualAsWritten());
     168               64:   Record.push_back(D->isPure());
     169               64:   Record.push_back(D->hasInheritedPrototype());
     170               64:   Record.push_back(D->hasWrittenPrototype());
     171               64:   Record.push_back(D->isDeleted());
     172               64:   Record.push_back(D->isTrivial());
     173               64:   Record.push_back(D->isCopyAssignment());
     174               64:   Record.push_back(D->hasImplicitReturnZero());
     175               64:   Writer.AddSourceLocation(D->getLocEnd(), Record);
     176                 :   // FIXME: C++ TemplateOrInstantiation
     177               64:   Record.push_back(D->param_size());
                       60: branch 2 taken
                       64: branch 3 taken
     178              124:   for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
     179                 :        P != PEnd; ++P)
     180               60:     Writer.AddDeclRef(*P, Record);
     181               64:   Code = pch::DECL_FUNCTION;
     182               64: }
     183                 : 
     184               29: void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
     185               29:   VisitNamedDecl(D);
     186                 :   // FIXME: convert to LazyStmtPtr?
     187                 :   // Unlike C/C++, method bodies will never be in header files.
     188               29:   Record.push_back(D->getBody() != 0);
                        3: branch 1 taken
                       26: branch 2 taken
     189               29:   if (D->getBody() != 0) {
     190                3:     Writer.AddStmt(D->getBody());
     191                3:     Writer.AddDeclRef(D->getSelfDecl(), Record);
     192                3:     Writer.AddDeclRef(D->getCmdDecl(), Record);
     193                 :   }
     194               29:   Record.push_back(D->isInstanceMethod());
     195               29:   Record.push_back(D->isVariadic());
     196               29:   Record.push_back(D->isSynthesized());
     197                 :   // FIXME: stable encoding for @required/@optional
     198               29:   Record.push_back(D->getImplementationControl());
     199                 :   // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway
     200               29:   Record.push_back(D->getObjCDeclQualifier());
     201               29:   Writer.AddTypeRef(D->getResultType(), Record);
     202               29:   Writer.AddSourceLocation(D->getLocEnd(), Record);
     203               29:   Record.push_back(D->param_size());
                        8: branch 1 taken
                       29: branch 2 taken
     204               66:   for (ObjCMethodDecl::param_iterator P = D->param_begin(),
     205               29:                                    PEnd = D->param_end(); P != PEnd; ++P)
     206                8:     Writer.AddDeclRef(*P, Record);
     207               29:   Code = pch::DECL_OBJC_METHOD;
     208               29: }
     209                 : 
     210               34: void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
     211               34:   VisitNamedDecl(D);
     212               34:   SourceRange R = D->getAtEndRange();
     213               34:   Writer.AddSourceLocation(R.getBegin(), Record);
     214               34:   Writer.AddSourceLocation(R.getEnd(), Record);
     215                 :   // Abstract class (no need to define a stable pch::DECL code).
     216               34: }
     217                 : 
     218               25: void PCHDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
     219               25:   VisitObjCContainerDecl(D);
     220               25:   Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
     221               25:   Writer.AddDeclRef(D->getSuperClass(), Record);
     222               25:   Record.push_back(D->protocol_size());
                        2: branch 1 taken
                       25: branch 2 taken
     223               52:   for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
     224               25:          PEnd = D->protocol_end();
     225                 :        P != PEnd; ++P)
     226                2:     Writer.AddDeclRef(*P, Record);
                        2: branch 1 taken
                       25: branch 2 taken
     227               52:   for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
     228               25:          PLEnd = D->protocol_loc_end();
     229                 :        PL != PLEnd; ++PL)
     230                2:     Writer.AddSourceLocation(*PL, Record);
     231               25:   Record.push_back(D->ivar_size());
                        4: branch 1 taken
                       25: branch 2 taken
     232               54:   for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
     233               25:                                      IEnd = D->ivar_end(); I != IEnd; ++I)
     234                4:     Writer.AddDeclRef(*I, Record);
     235               25:   Writer.AddDeclRef(D->getCategoryList(), Record);
     236               25:   Record.push_back(D->isForwardDecl());
     237               25:   Record.push_back(D->isImplicitInterfaceDecl());
     238               25:   Writer.AddSourceLocation(D->getClassLoc(), Record);
     239               25:   Writer.AddSourceLocation(D->getSuperClassLoc(), Record);
     240               25:   Writer.AddSourceLocation(D->getLocEnd(), Record);
     241               25:   Code = pch::DECL_OBJC_INTERFACE;
     242               25: }
     243                 : 
     244                4: void PCHDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
     245                4:   VisitFieldDecl(D);
     246                 :   // FIXME: stable encoding for @public/@private/@protected/@package
     247                4:   Record.push_back(D->getAccessControl());
     248                4:   Code = pch::DECL_OBJC_IVAR;
     249                4: }
     250                 : 
     251                5: void PCHDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
     252                5:   VisitObjCContainerDecl(D);
     253                5:   Record.push_back(D->isForwardDecl());
     254                5:   Writer.AddSourceLocation(D->getLocEnd(), Record);
     255                5:   Record.push_back(D->protocol_size());
                        2: branch 0 taken
                        5: branch 1 taken
     256                7:   for (ObjCProtocolDecl::protocol_iterator
     257                5:        I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
     258                2:     Writer.AddDeclRef(*I, Record);
                        2: branch 1 taken
                        5: branch 2 taken
     259               12:   for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
     260                5:          PLEnd = D->protocol_loc_end();
     261                 :        PL != PLEnd; ++PL)
     262                2:     Writer.AddSourceLocation(*PL, Record);
     263                5:   Code = pch::DECL_OBJC_PROTOCOL;
     264                5: }
     265                 : 
     266                0: void PCHDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
     267                0:   VisitFieldDecl(D);
     268                0:   Code = pch::DECL_OBJC_AT_DEFS_FIELD;
     269                0: }
     270                 : 
     271                4: void PCHDeclWriter::VisitObjCClassDecl(ObjCClassDecl *D) {
     272                4:   VisitDecl(D);
     273                4:   Record.push_back(D->size());
                        4: branch 2 taken
                        4: branch 3 taken
     274                8:   for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
     275                4:     Writer.AddDeclRef(I->getInterface(), Record);
                        4: branch 2 taken
                        4: branch 3 taken
     276                8:   for (ObjCClassDecl::iterator I = D->begin(), IEnd = D->end(); I != IEnd; ++I)
     277                4:     Writer.AddSourceLocation(I->getLocation(), Record);
     278                4:   Code = pch::DECL_OBJC_CLASS;
     279                4: }
     280                 : 
     281                1: void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
     282                1:   VisitDecl(D);
     283                1:   Record.push_back(D->protocol_size());
                        1: branch 0 taken
                        1: branch 1 taken
     284                2:   for (ObjCForwardProtocolDecl::protocol_iterator
     285                1:        I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
     286                1:     Writer.AddDeclRef(*I, Record);
                        1: branch 0 taken
                        1: branch 1 taken
     287                2:   for (ObjCForwardProtocolDecl::protocol_loc_iterator 
     288                1:          PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
     289                 :        PL != PLEnd; ++PL)
     290                1:     Writer.AddSourceLocation(*PL, Record);
     291                1:   Code = pch::DECL_OBJC_FORWARD_PROTOCOL;
     292                1: }
     293                 : 
     294                2: void PCHDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
     295                2:   VisitObjCContainerDecl(D);
     296                2:   Writer.AddDeclRef(D->getClassInterface(), Record);
     297                2:   Record.push_back(D->protocol_size());
                        0: branch 0 not taken
                        2: branch 1 taken
     298                2:   for (ObjCCategoryDecl::protocol_iterator
     299                2:        I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
     300                0:     Writer.AddDeclRef(*I, Record);
                        0: branch 0 not taken
                        2: branch 1 taken
     301                2:   for (ObjCCategoryDecl::protocol_loc_iterator 
     302                2:          PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
     303                 :        PL != PLEnd; ++PL)
     304                0:     Writer.AddSourceLocation(*PL, Record);
     305                2:   Writer.AddDeclRef(D->getNextClassCategory(), Record);
     306                2:   Writer.AddSourceLocation(D->getAtLoc(), Record);
     307                2:   Writer.AddSourceLocation(D->getCategoryNameLoc(), Record);
     308                2:   Code = pch::DECL_OBJC_CATEGORY;
     309                2: }
     310                 : 
     311                0: void PCHDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
     312                0:   VisitNamedDecl(D);
     313                0:   Writer.AddDeclRef(D->getClassInterface(), Record);
     314                0:   Code = pch::DECL_OBJC_COMPATIBLE_ALIAS;
     315                0: }
     316                 : 
     317                2: void PCHDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
     318                2:   VisitNamedDecl(D);
     319                2:   Writer.AddSourceLocation(D->getAtLoc(), Record);
     320                2:   Writer.AddTypeRef(D->getType(), Record);
     321                 :   // FIXME: stable encoding
     322                2:   Record.push_back((unsigned)D->getPropertyAttributes());
     323                 :   // FIXME: stable encoding
     324                2:   Record.push_back((unsigned)D->getPropertyImplementation());
     325                2:   Writer.AddDeclarationName(D->getGetterName(), Record);
     326                2:   Writer.AddDeclarationName(D->getSetterName(), Record);
     327                2:   Writer.AddDeclRef(D->getGetterMethodDecl(), Record);
     328                2:   Writer.AddDeclRef(D->getSetterMethodDecl(), Record);
     329                2:   Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
     330                2:   Code = pch::DECL_OBJC_PROPERTY;
     331                2: }
     332                 : 
     333                2: void PCHDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) {
     334                2:   VisitObjCContainerDecl(D);
     335                2:   Writer.AddDeclRef(D->getClassInterface(), Record);
     336                 :   // Abstract class (no need to define a stable pch::DECL code).
     337                2: }
     338                 : 
     339                0: void PCHDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
     340                0:   VisitObjCImplDecl(D);
     341                0:   Writer.AddIdentifierRef(D->getIdentifier(), Record);
     342                0:   Code = pch::DECL_OBJC_CATEGORY_IMPL;
     343                0: }
     344                 : 
     345                2: void PCHDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
     346                2:   VisitObjCImplDecl(D);
     347                2:   Writer.AddDeclRef(D->getSuperClass(), Record);
     348                2:   Code = pch::DECL_OBJC_IMPLEMENTATION;
     349                2: }
     350                 : 
     351                0: void PCHDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
     352                0:   VisitDecl(D);
     353                0:   Writer.AddSourceLocation(D->getLocStart(), Record);
     354                0:   Writer.AddDeclRef(D->getPropertyDecl(), Record);
     355                0:   Writer.AddDeclRef(D->getPropertyIvarDecl(), Record);
     356                0:   Code = pch::DECL_OBJC_PROPERTY_IMPL;
     357                0: }
     358                 : 
     359               51: void PCHDeclWriter::VisitFieldDecl(FieldDecl *D) {
     360               51:   VisitDeclaratorDecl(D);
     361               51:   Record.push_back(D->isMutable());
                        1: branch 1 taken
                       50: branch 2 taken
     362               51:   Record.push_back(D->getBitWidth()? 1 : 0);
                        1: branch 1 taken
                       50: branch 2 taken
     363               51:   if (D->getBitWidth())
     364                1:     Writer.AddStmt(D->getBitWidth());
     365               51:   Code = pch::DECL_FIELD;
     366               51: }
     367                 : 
     368              169: void PCHDeclWriter::VisitVarDecl(VarDecl *D) {
     369              169:   VisitDeclaratorDecl(D);
     370              169:   Record.push_back(D->getStorageClass()); // FIXME: stable encoding
     371              169:   Record.push_back(D->isThreadSpecified());
     372              169:   Record.push_back(D->hasCXXDirectInitializer());
     373              169:   Record.push_back(D->isDeclaredInCondition());
     374              169:   Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
                       28: branch 1 taken
                      141: branch 2 taken
     375              169:   Record.push_back(D->getInit()? 1 : 0);
                       28: branch 1 taken
                      141: branch 2 taken
     376              169:   if (D->getInit())
     377               28:     Writer.AddStmt(D->getInit());
     378              169:   Code = pch::DECL_VAR;
     379              169: }
     380                 : 
     381                6: void PCHDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
     382                6:   VisitVarDecl(D);
     383                6:   Code = pch::DECL_IMPLICIT_PARAM;
     384                6: }
     385                 : 
     386               80: void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
     387               80:   VisitVarDecl(D);
     388               80:   Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding
     389               80:   Code = pch::DECL_PARM_VAR;
     390                 : 
     391                 : 
     392                 :   // If the assumptions about the DECL_PARM_VAR abbrev are true, use it.  Here
     393                 :   // we dynamically check for the properties that we optimize for, but don't
     394                 :   // know are true of all PARM_VAR_DECLs.
                       13: branch 1 taken
                       67: branch 2 taken
                       13: branch 4 taken
                        0: branch 5 not taken
                       13: branch 7 taken
                        0: branch 8 not taken
                       13: branch 10 taken
                        0: branch 11 not taken
                       13: branch 13 taken
                        0: branch 14 not taken
                       13: branch 16 taken
                        0: branch 17 not taken
                       13: branch 19 taken
                        0: branch 20 not taken
                       13: branch 22 taken
                        0: branch 23 not taken
                       13: branch 25 taken
                        0: branch 26 not taken
                       13: branch 27 taken
                       67: branch 28 taken
     395               80:   if (!D->getTypeSourceInfo() &&
     396                 :       !D->hasAttrs() &&
     397                 :       !D->isImplicit() &&
     398                 :       !D->isUsed() &&
     399                 :       D->getAccess() == AS_none &&
     400                 :       D->getPCHLevel() == 0 &&
     401                 :       D->getStorageClass() == 0 &&
     402                 :       !D->hasCXXDirectInitializer() && // Can params have this ever?
     403                 :       D->getObjCDeclQualifier() == 0)
     404               13:     AbbrevToUse = Writer.getParmVarDeclAbbrev();
     405                 : 
     406                 :   // Check things we know are true of *every* PARM_VAR_DECL, which is more than
     407                 :   // just us assuming it.
                       80: branch 1 taken
                        0: branch 2 not taken
     408               80:   assert(!D->isInvalidDecl() && "Shouldn't emit invalid decls");
                       80: branch 1 taken
                        0: branch 2 not taken
     409               80:   assert(!D->isThreadSpecified() && "PARM_VAR_DECL can't be __thread");
                       80: branch 1 taken
                        0: branch 2 not taken
     410               80:   assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
                       80: branch 1 taken
                        0: branch 2 not taken
     411               80:   assert(!D->isDeclaredInCondition() && "PARM_VAR_DECL can't be in condition");
                       80: branch 1 taken
                        0: branch 2 not taken
     412               80:   assert(D->getPreviousDeclaration() == 0 && "PARM_VAR_DECL can't be redecl");
                       80: branch 1 taken
                        0: branch 2 not taken
     413               80:   assert(D->getInit() == 0 && "PARM_VAR_DECL never has init");
     414               80: }
     415                 : 
     416                1: void PCHDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
     417                1:   VisitDecl(D);
     418                1:   Writer.AddStmt(D->getAsmString());
     419                1:   Code = pch::DECL_FILE_SCOPE_ASM;
     420                1: }
     421                 : 
     422                2: void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) {
     423                2:   VisitDecl(D);
     424                2:   Writer.AddStmt(D->getBody());
     425                2:   Record.push_back(D->param_size());
                        4: branch 2 taken
                        2: branch 3 taken
     426                6:   for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
     427                 :        P != PEnd; ++P)
     428                4:     Writer.AddDeclRef(*P, Record);
     429                2:   Code = pch::DECL_BLOCK;
     430                2: }
     431                 : 
     432                 : /// \brief Emit the DeclContext part of a declaration context decl.
     433                 : ///
     434                 : /// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL
     435                 : /// block for this declaration context is stored. May be 0 to indicate
     436                 : /// that there are no declarations stored within this context.
     437                 : ///
     438                 : /// \param VisibleOffset the offset at which the DECL_CONTEXT_VISIBLE
     439                 : /// block for this declaration context is stored. May be 0 to indicate
     440                 : /// that there are no declarations visible from this context. Note
     441                 : /// that this value will not be emitted for non-primary declaration
     442                 : /// contexts.
     443                 : void PCHDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
     444              208:                                      uint64_t VisibleOffset) {
     445              208:   Record.push_back(LexicalOffset);
     446              208:   Record.push_back(VisibleOffset);
     447              208: }
     448                 : 
     449                 : 
     450                 : //===----------------------------------------------------------------------===//
     451                 : // PCHWriter Implementation
     452                 : //===----------------------------------------------------------------------===//
     453                 : 
     454               44: void PCHWriter::WriteDeclsBlockAbbrevs() {
     455                 :   using namespace llvm;
     456                 :   // Abbreviation for DECL_PARM_VAR.
     457               44:   BitCodeAbbrev *Abv = new BitCodeAbbrev();
     458               44:   Abv->Add(BitCodeAbbrevOp(pch::DECL_PARM_VAR));
     459                 : 
     460                 :   // Decl
     461               44:   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
     462               44:   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext
     463               44:   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
     464               44:   Abv->Add(BitCodeAbbrevOp(0));                       // isInvalidDecl (!?)
     465               44:   Abv->Add(BitCodeAbbrevOp(0));                       // HasAttrs
     466               44:   Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit
     467               44:   Abv->Add(BitCodeAbbrevOp(0));                       // isUsed
     468               44:   Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier
     469               44:   Abv->Add(BitCodeAbbrevOp(0));                       // PCH level
     470                 : 
     471                 :   // NamedDecl
     472               44:   Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
     473               44:   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
     474                 :   // ValueDecl
     475               44:   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
     476                 :   // DeclaratorDecl
     477               44:   Abv->Add(BitCodeAbbrevOp(pch::PREDEF_TYPE_NULL_ID)); // InfoType
     478                 :   // VarDecl
     479               44:   Abv->Add(BitCodeAbbrevOp(0));                       // StorageClass
     480               44:   Abv->Add(BitCodeAbbrevOp(0));                       // isThreadSpecified
     481               44:   Abv->Add(BitCodeAbbrevOp(0));                       // hasCXXDirectInitializer
     482               44:   Abv->Add(BitCodeAbbrevOp(0));                       // isDeclaredInCondition
     483               44:   Abv->Add(BitCodeAbbrevOp(0));                       // PrevDecl
     484               44:   Abv->Add(BitCodeAbbrevOp(0));                       // HasInit
     485                 :   // ParmVarDecl
     486               44:   Abv->Add(BitCodeAbbrevOp(0));                       // ObjCDeclQualifier
     487                 : 
     488               44:   ParmVarDeclAbbrev = Stream.EmitAbbrev(Abv);
     489               44: }
     490                 : 
     491                 : /// isRequiredDecl - Check if this is a "required" Decl, which must be seen by
     492                 : /// consumers of the AST.
     493                 : ///
     494                 : /// Such decls will always be deserialized from the PCH file, so we would like
     495                 : /// this to be as restrictive as possible. Currently the predicate is driven by
     496                 : /// code generation requirements, if other clients have a different notion of
     497                 : /// what is "required" then we may have to consider an alternate scheme where
     498                 : /// clients can iterate over the top-level decls and get information on them,
     499                 : /// without necessary deserializing them. We could explicitly require such
     500                 : /// clients to use a separate API call to "realize" the decl. This should be
     501                 : /// relatively painless since they would presumably only do it for top-level
     502                 : /// decls.
     503                 : //
     504                 : // FIXME: This predicate is essentially IRgen's predicate to determine whether a
     505                 : // declaration can be deferred. Merge them somehow.
     506              602: static bool isRequiredDecl(const Decl *D, ASTContext &Context) {
     507                 :   // File scoped assembly must be seen.
                        1: branch 1 taken
                      601: branch 2 taken
     508              602:   if (isa<FileScopeAsmDecl>(D))
     509                1:     return true;
     510                 : 
     511                 :   // Otherwise if this isn't a function or a file scoped variable it doesn't
     512                 :   // need to be seen.
                      169: branch 1 taken
                      432: branch 2 taken
     513              601:   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
                      114: branch 1 taken
                       55: branch 2 taken
     514              169:     if (!VD->isFileVarDecl())
     515              114:       return false;
                      368: branch 1 taken
                       64: branch 2 taken
     516              432:   } else if (!isa<FunctionDecl>(D))
     517              368:     return false;
     518                 : 
     519                 :   // Aliases and used decls must be seen.
                      119: branch 1 taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                      119: branch 5 taken
                        0: branch 6 not taken
                      119: branch 7 taken
     520              119:   if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
     521                0:     return true;
     522                 : 
                       64: branch 1 taken
                       55: branch 2 taken
     523              119:   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     524                 :     // Forward declarations don't need to be seen.
                       37: branch 1 taken
                       27: branch 2 taken
     525               64:     if (!FD->isThisDeclarationADefinition())
     526               37:       return false;
     527                 : 
     528                 :     // Constructors and destructors must be seen.
                       27: branch 1 taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                       27: branch 5 taken
                        0: branch 6 not taken
                       27: branch 7 taken
     529               27:     if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
     530                0:       return true;
     531                 : 
     532                 :     // Otherwise, this is required unless it is static.
     533                 :     //
     534                 :     // FIXME: Inlines.
     535               27:     return FD->getStorageClass() != FunctionDecl::Static;
     536                 :   } else {
     537               55:     const VarDecl *VD = cast<VarDecl>(D);
     538                 : 
     539                 :     // In C++, this doesn't need to be seen if it is marked "extern".
                        5: branch 1 taken
                       50: branch 2 taken
                        3: branch 4 taken
                        2: branch 5 taken
                        3: branch 7 taken
                        0: branch 8 not taken
                        0: branch 10 not taken
                        3: branch 11 taken
                        0: branch 12 not taken
                       55: branch 13 taken
     540               55:     if (Context.getLangOptions().CPlusPlus && !VD->getInit() &&
     541                 :         (VD->getStorageClass() == VarDecl::Extern ||
     542                 :          VD->isExternC()))
     543                0:       return false;
     544                 : 
     545                 :     // In C, this doesn't need to be seen unless it is a definition.
                       50: branch 1 taken
                        5: branch 2 taken
                       40: branch 4 taken
                       10: branch 5 taken
                       40: branch 6 taken
                       15: branch 7 taken
     546               55:     if (!Context.getLangOptions().CPlusPlus && !VD->getInit())
     547               40:       return false;
     548                 : 
     549                 :     // Otherwise, this is required unless it is static.
     550               15:     return VD->getStorageClass() != VarDecl::Static;
     551                 :   }
     552                 : }
     553                 : 
     554              602: void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
     555              602:   RecordData Record;
     556              602:   PCHDeclWriter W(*this, Context, Record);
     557                 : 
     558                 :   // If this declaration is also a DeclContext, write blocks for the
     559                 :   // declarations that lexically stored inside its context and those
     560                 :   // declarations that are visible from its context. These blocks
     561                 :   // are written before the declaration itself so that we can put
     562                 :   // their offsets into the record for the declaration.
     563              602:   uint64_t LexicalOffset = 0;
     564              602:   uint64_t VisibleOffset = 0;
     565              602:   DeclContext *DC = dyn_cast<DeclContext>(D);
                      208: branch 0 taken
                      394: branch 1 taken
     566              602:   if (DC) {
     567              208:     LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
     568              208:     VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
     569                 :   }
     570                 : 
     571                 :   // Determine the ID for this declaration
     572              602:   pch::DeclID &ID = DeclIDs[D];
                        0: branch 0 not taken
                      602: branch 1 taken
     573              602:   if (ID == 0)
     574                0:     ID = DeclIDs.size();
     575                 : 
     576              602:   unsigned Index = ID - 1;
     577                 : 
     578                 :   // Record the offset for this declaration
                      602: branch 1 taken
                        0: branch 2 not taken
     579              602:   if (DeclOffsets.size() == Index)
     580              602:     DeclOffsets.push_back(Stream.GetCurrentBitNo());
                        0: branch 1 not taken
                        0: branch 2 not taken
     581                0:   else if (DeclOffsets.size() < Index) {
     582                0:     DeclOffsets.resize(Index+1);
     583                0:     DeclOffsets[Index] = Stream.GetCurrentBitNo();
     584                 :   }
     585                 : 
     586                 :   // Build and emit a record for this declaration
     587              602:   Record.clear();
     588              602:   W.Code = (pch::DeclCode)0;
     589              602:   W.AbbrevToUse = 0;
     590              602:   W.Visit(D);
                      208: branch 0 taken
                      394: branch 1 taken
     591              602:   if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
     592                 : 
                        0: branch 0 not taken
                      602: branch 1 taken
     593              602:   if (!W.Code)
     594                 :     llvm::llvm_report_error(llvm::StringRef("unexpected declaration kind '") +
     595                0:                             D->getDeclKindName() + "'");
     596              602:   Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
     597                 : 
     598                 :   // If the declaration had any attributes, write them now.
                        7: branch 1 taken
                      595: branch 2 taken
     599              602:   if (D->hasAttrs())
     600                7:     WriteAttributeRecord(D->getAttrs());
     601                 : 
     602                 :   // Flush any expressions that were written as part of this declaration.
     603              602:   FlushStmts();
     604                 : 
     605                 :   // Note "external" declarations so that we can add them to a record in the
     606                 :   // PCH file later.
     607                 :   //
     608                 :   // FIXME: This should be renamed, the predicate is much more complicated.
                       42: branch 1 taken
                      560: branch 2 taken
     609              602:   if (isRequiredDecl(D, Context))
     610               42:     ExternalDefinitions.push_back(Index + 1);
     611              602: }

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