| //===--- PCHReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // This file implements the PCHReader::ReadDeclRecord method, which is the | 
 | // entrypoint for loading a decl. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "clang/Frontend/PCHReader.h" | 
 | #include "clang/AST/ASTConsumer.h" | 
 | #include "clang/AST/ASTContext.h" | 
 | #include "clang/AST/DeclVisitor.h" | 
 | #include "clang/AST/DeclGroup.h" | 
 | #include "clang/AST/Expr.h" | 
 | using namespace clang; | 
 |  | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // Declaration deserialization | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | namespace { | 
 |   class PCHDeclReader : public DeclVisitor<PCHDeclReader, void> { | 
 |     PCHReader &Reader; | 
 |     const PCHReader::RecordData &Record; | 
 |     unsigned &Idx; | 
 |  | 
 |   public: | 
 |     PCHDeclReader(PCHReader &Reader, const PCHReader::RecordData &Record, | 
 |                   unsigned &Idx) | 
 |       : Reader(Reader), Record(Record), Idx(Idx) { } | 
 |  | 
 |     void VisitDecl(Decl *D); | 
 |     void VisitTranslationUnitDecl(TranslationUnitDecl *TU); | 
 |     void VisitNamedDecl(NamedDecl *ND); | 
 |     void VisitTypeDecl(TypeDecl *TD); | 
 |     void VisitTypedefDecl(TypedefDecl *TD); | 
 |     void VisitTagDecl(TagDecl *TD); | 
 |     void VisitEnumDecl(EnumDecl *ED); | 
 |     void VisitRecordDecl(RecordDecl *RD); | 
 |     void VisitValueDecl(ValueDecl *VD); | 
 |     void VisitEnumConstantDecl(EnumConstantDecl *ECD); | 
 |     void VisitFunctionDecl(FunctionDecl *FD); | 
 |     void VisitFieldDecl(FieldDecl *FD); | 
 |     void VisitVarDecl(VarDecl *VD); | 
 |     void VisitImplicitParamDecl(ImplicitParamDecl *PD); | 
 |     void VisitParmVarDecl(ParmVarDecl *PD); | 
 |     void VisitOriginalParmVarDecl(OriginalParmVarDecl *PD); | 
 |     void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); | 
 |     void VisitBlockDecl(BlockDecl *BD); | 
 |     std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC); | 
 |     void VisitObjCMethodDecl(ObjCMethodDecl *D); | 
 |     void VisitObjCContainerDecl(ObjCContainerDecl *D); | 
 |     void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); | 
 |     void VisitObjCIvarDecl(ObjCIvarDecl *D); | 
 |     void VisitObjCProtocolDecl(ObjCProtocolDecl *D); | 
 |     void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D); | 
 |     void VisitObjCClassDecl(ObjCClassDecl *D); | 
 |     void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); | 
 |     void VisitObjCCategoryDecl(ObjCCategoryDecl *D); | 
 |     void VisitObjCImplDecl(ObjCImplDecl *D); | 
 |     void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); | 
 |     void VisitObjCImplementationDecl(ObjCImplementationDecl *D); | 
 |     void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); | 
 |     void VisitObjCPropertyDecl(ObjCPropertyDecl *D); | 
 |     void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); | 
 |   }; | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitDecl(Decl *D) { | 
 |   D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]))); | 
 |   D->setLexicalDeclContext( | 
 |                      cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++]))); | 
 |   D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 |   D->setInvalidDecl(Record[Idx++]); | 
 |   if (Record[Idx++]) | 
 |     D->addAttr(Reader.ReadAttributes()); | 
 |   D->setImplicit(Record[Idx++]); | 
 |   D->setAccess((AccessSpecifier)Record[Idx++]); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { | 
 |   VisitDecl(TU); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) { | 
 |   VisitDecl(ND); | 
 |   ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));   | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) { | 
 |   VisitNamedDecl(TD); | 
 |   TD->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr()); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) { | 
 |   // Note that we cannot use VisitTypeDecl here, because we need to | 
 |   // set the underlying type of the typedef *before* we try to read | 
 |   // the type associated with the TypedefDecl. | 
 |   VisitNamedDecl(TD); | 
 |   TD->setUnderlyingType(Reader.GetType(Record[Idx + 1])); | 
 |   TD->setTypeForDecl(Reader.GetType(Record[Idx]).getTypePtr()); | 
 |   Idx += 2; | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitTagDecl(TagDecl *TD) { | 
 |   VisitTypeDecl(TD); | 
 |   TD->setTagKind((TagDecl::TagKind)Record[Idx++]); | 
 |   TD->setDefinition(Record[Idx++]); | 
 |   TD->setTypedefForAnonDecl( | 
 |                     cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++]))); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) { | 
 |   VisitTagDecl(ED); | 
 |   ED->setIntegerType(Reader.GetType(Record[Idx++])); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) { | 
 |   VisitTagDecl(RD); | 
 |   RD->setHasFlexibleArrayMember(Record[Idx++]); | 
 |   RD->setAnonymousStructOrUnion(Record[Idx++]); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitValueDecl(ValueDecl *VD) { | 
 |   VisitNamedDecl(VD); | 
 |   VD->setType(Reader.GetType(Record[Idx++])); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { | 
 |   VisitValueDecl(ECD); | 
 |   if (Record[Idx++]) | 
 |     ECD->setInitExpr(Reader.ReadDeclExpr()); | 
 |   ECD->setInitVal(Reader.ReadAPSInt(Record, Idx)); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { | 
 |   VisitValueDecl(FD); | 
 |   if (Record[Idx++]) | 
 |     FD->setLazyBody(Reader.getDeclsCursor().GetCurrentBitNo()); | 
 |   FD->setPreviousDeclaration( | 
 |                    cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]); | 
 |   FD->setInline(Record[Idx++]); | 
 |   FD->setC99InlineDefinition(Record[Idx++]); | 
 |   FD->setVirtual(Record[Idx++]); | 
 |   FD->setPure(Record[Idx++]); | 
 |   FD->setInheritedPrototype(Record[Idx++]); | 
 |   FD->setHasPrototype(Record[Idx++]); | 
 |   FD->setDeleted(Record[Idx++]); | 
 |   FD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 |   unsigned NumParams = Record[Idx++]; | 
 |   llvm::SmallVector<ParmVarDecl *, 16> Params; | 
 |   Params.reserve(NumParams); | 
 |   for (unsigned I = 0; I != NumParams; ++I) | 
 |     Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   FD->setParams(*Reader.getContext(), &Params[0], NumParams); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { | 
 |   VisitNamedDecl(MD); | 
 |   if (Record[Idx++]) { | 
 |     // In practice, this won't be executed (since method definitions | 
 |     // don't occur in header files). | 
 |     MD->setBody(Reader.ReadDeclStmt()); | 
 |     MD->setSelfDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |     MD->setCmdDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   } | 
 |   MD->setInstanceMethod(Record[Idx++]); | 
 |   MD->setVariadic(Record[Idx++]); | 
 |   MD->setSynthesized(Record[Idx++]); | 
 |   MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]); | 
 |   MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); | 
 |   MD->setResultType(Reader.GetType(Record[Idx++])); | 
 |   MD->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 |   unsigned NumParams = Record[Idx++]; | 
 |   llvm::SmallVector<ParmVarDecl *, 16> Params; | 
 |   Params.reserve(NumParams); | 
 |   for (unsigned I = 0; I != NumParams; ++I) | 
 |     Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   MD->setMethodParams(*Reader.getContext(), &Params[0], NumParams); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { | 
 |   VisitNamedDecl(CD); | 
 |   CD->setAtEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { | 
 |   VisitObjCContainerDecl(ID); | 
 |   ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr()); | 
 |   ID->setSuperClass(cast_or_null<ObjCInterfaceDecl> | 
 |                        (Reader.GetDecl(Record[Idx++]))); | 
 |   unsigned NumProtocols = Record[Idx++]; | 
 |   llvm::SmallVector<ObjCProtocolDecl *, 16> Protocols; | 
 |   Protocols.reserve(NumProtocols); | 
 |   for (unsigned I = 0; I != NumProtocols; ++I) | 
 |     Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   ID->setProtocolList(&Protocols[0], NumProtocols, *Reader.getContext()); | 
 |   unsigned NumIvars = Record[Idx++]; | 
 |   llvm::SmallVector<ObjCIvarDecl *, 16> IVars; | 
 |   IVars.reserve(NumIvars); | 
 |   for (unsigned I = 0; I != NumIvars; ++I) | 
 |     IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   ID->setIVarList(&IVars[0], NumIvars, *Reader.getContext()); | 
 |   ID->setCategoryList( | 
 |                cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   ID->setForwardDecl(Record[Idx++]); | 
 |   ID->setImplicitInterfaceDecl(Record[Idx++]); | 
 |   ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 |   ID->setSuperClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 |   ID->setAtEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { | 
 |   VisitFieldDecl(IVD); | 
 |   IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { | 
 |   VisitObjCContainerDecl(PD); | 
 |   PD->setForwardDecl(Record[Idx++]); | 
 |   PD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 |   unsigned NumProtoRefs = Record[Idx++]; | 
 |   llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; | 
 |   ProtoRefs.reserve(NumProtoRefs); | 
 |   for (unsigned I = 0; I != NumProtoRefs; ++I) | 
 |     ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   PD->setProtocolList(&ProtoRefs[0], NumProtoRefs, *Reader.getContext()); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) { | 
 |   VisitFieldDecl(FD); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) { | 
 |   VisitDecl(CD); | 
 |   unsigned NumClassRefs = Record[Idx++]; | 
 |   llvm::SmallVector<ObjCInterfaceDecl *, 16> ClassRefs; | 
 |   ClassRefs.reserve(NumClassRefs); | 
 |   for (unsigned I = 0; I != NumClassRefs; ++I) | 
 |     ClassRefs.push_back(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   CD->setClassList(*Reader.getContext(), &ClassRefs[0], NumClassRefs); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) { | 
 |   VisitDecl(FPD); | 
 |   unsigned NumProtoRefs = Record[Idx++]; | 
 |   llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; | 
 |   ProtoRefs.reserve(NumProtoRefs); | 
 |   for (unsigned I = 0; I != NumProtoRefs; ++I) | 
 |     ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   FPD->setProtocolList(&ProtoRefs[0], NumProtoRefs, *Reader.getContext()); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { | 
 |   VisitObjCContainerDecl(CD); | 
 |   CD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   unsigned NumProtoRefs = Record[Idx++]; | 
 |   llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; | 
 |   ProtoRefs.reserve(NumProtoRefs); | 
 |   for (unsigned I = 0; I != NumProtoRefs; ++I) | 
 |     ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   CD->setProtocolList(&ProtoRefs[0], NumProtoRefs, *Reader.getContext()); | 
 |   CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   CD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { | 
 |   VisitNamedDecl(CAD); | 
 |   CAD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { | 
 |   VisitNamedDecl(D); | 
 |   D->setType(Reader.GetType(Record[Idx++])); | 
 |   // FIXME: stable encoding | 
 |   D->setPropertyAttributes( | 
 |                       (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]); | 
 |   // FIXME: stable encoding | 
 |   D->setPropertyImplementation( | 
 |                             (ObjCPropertyDecl::PropertyControl)Record[Idx++]); | 
 |   D->setGetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector()); | 
 |   D->setSetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector()); | 
 |   D->setGetterMethodDecl( | 
 |                  cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   D->setSetterMethodDecl( | 
 |                  cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   D->setPropertyIvarDecl( | 
 |                    cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) { | 
 |   VisitNamedDecl(D); | 
 |   D->setClassInterface( | 
 |               cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   D->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { | 
 |   VisitObjCImplDecl(D); | 
 |   D->setIdentifier(Reader.GetIdentifierInfo(Record, Idx)); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { | 
 |   VisitObjCImplDecl(D); | 
 |   D->setSuperClass( | 
 |               cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++]))); | 
 | } | 
 |  | 
 |  | 
 | void PCHDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { | 
 |   VisitDecl(D); | 
 |   D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 |   D->setPropertyDecl( | 
 |                cast_or_null<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   D->setPropertyIvarDecl( | 
 |                    cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++]))); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) { | 
 |   VisitValueDecl(FD); | 
 |   FD->setMutable(Record[Idx++]); | 
 |   if (Record[Idx++]) | 
 |     FD->setBitWidth(Reader.ReadDeclExpr()); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitVarDecl(VarDecl *VD) { | 
 |   VisitValueDecl(VD); | 
 |   VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]); | 
 |   VD->setThreadSpecified(Record[Idx++]); | 
 |   VD->setCXXDirectInitializer(Record[Idx++]); | 
 |   VD->setDeclaredInCondition(Record[Idx++]); | 
 |   VD->setPreviousDeclaration( | 
 |                          cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   VD->setTypeSpecStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); | 
 |   if (Record[Idx++]) | 
 |     VD->setInit(Reader.ReadDeclExpr()); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { | 
 |   VisitVarDecl(PD); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { | 
 |   VisitVarDecl(PD); | 
 |   PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]); | 
 |   // FIXME: default argument (C++ only) | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitOriginalParmVarDecl(OriginalParmVarDecl *PD) { | 
 |   VisitParmVarDecl(PD); | 
 |   PD->setOriginalType(Reader.GetType(Record[Idx++])); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) { | 
 |   VisitDecl(AD); | 
 |   AD->setAsmString(cast<StringLiteral>(Reader.ReadDeclExpr())); | 
 | } | 
 |  | 
 | void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) { | 
 |   VisitDecl(BD); | 
 |   BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadDeclStmt())); | 
 |   unsigned NumParams = Record[Idx++]; | 
 |   llvm::SmallVector<ParmVarDecl *, 16> Params; | 
 |   Params.reserve(NumParams); | 
 |   for (unsigned I = 0; I != NumParams; ++I) | 
 |     Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); | 
 |   BD->setParams(*Reader.getContext(), &Params[0], NumParams);   | 
 | } | 
 |  | 
 | std::pair<uint64_t, uint64_t>  | 
 | PCHDeclReader::VisitDeclContext(DeclContext *DC) { | 
 |   uint64_t LexicalOffset = Record[Idx++]; | 
 |   uint64_t VisibleOffset = Record[Idx++]; | 
 |   return std::make_pair(LexicalOffset, VisibleOffset); | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // Attribute Reading | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | /// \brief Reads attributes from the current stream position. | 
 | Attr *PCHReader::ReadAttributes() { | 
 |   unsigned Code = DeclsCursor.ReadCode(); | 
 |   assert(Code == llvm::bitc::UNABBREV_RECORD &&  | 
 |          "Expected unabbreviated record"); (void)Code; | 
 |    | 
 |   RecordData Record; | 
 |   unsigned Idx = 0; | 
 |   unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); | 
 |   assert(RecCode == pch::DECL_ATTR && "Expected attribute record");  | 
 |   (void)RecCode; | 
 |  | 
 | #define SIMPLE_ATTR(Name)                       \ | 
 |  case Attr::Name:                               \ | 
 |    New = ::new (*Context) Name##Attr();         \ | 
 |    break | 
 |  | 
 | #define STRING_ATTR(Name)                                       \ | 
 |  case Attr::Name:                                               \ | 
 |    New = ::new (*Context) Name##Attr(ReadString(Record, Idx));  \ | 
 |    break | 
 |  | 
 | #define UNSIGNED_ATTR(Name)                             \ | 
 |  case Attr::Name:                                       \ | 
 |    New = ::new (*Context) Name##Attr(Record[Idx++]);    \ | 
 |    break | 
 |  | 
 |   Attr *Attrs = 0; | 
 |   while (Idx < Record.size()) { | 
 |     Attr *New = 0; | 
 |     Attr::Kind Kind = (Attr::Kind)Record[Idx++]; | 
 |     bool IsInherited = Record[Idx++]; | 
 |  | 
 |     switch (Kind) { | 
 |     STRING_ATTR(Alias); | 
 |     UNSIGNED_ATTR(Aligned); | 
 |     SIMPLE_ATTR(AlwaysInline); | 
 |     SIMPLE_ATTR(AnalyzerNoReturn); | 
 |     STRING_ATTR(Annotate); | 
 |     STRING_ATTR(AsmLabel); | 
 |      | 
 |     case Attr::Blocks: | 
 |       New = ::new (*Context) BlocksAttr( | 
 |                                   (BlocksAttr::BlocksAttrTypes)Record[Idx++]); | 
 |       break; | 
 |        | 
 |     case Attr::Cleanup: | 
 |       New = ::new (*Context) CleanupAttr( | 
 |                                   cast<FunctionDecl>(GetDecl(Record[Idx++]))); | 
 |       break; | 
 |  | 
 |     SIMPLE_ATTR(Const); | 
 |     UNSIGNED_ATTR(Constructor); | 
 |     SIMPLE_ATTR(DLLExport); | 
 |     SIMPLE_ATTR(DLLImport); | 
 |     SIMPLE_ATTR(Deprecated); | 
 |     UNSIGNED_ATTR(Destructor); | 
 |     SIMPLE_ATTR(FastCall); | 
 |      | 
 |     case Attr::Format: { | 
 |       std::string Type = ReadString(Record, Idx); | 
 |       unsigned FormatIdx = Record[Idx++]; | 
 |       unsigned FirstArg = Record[Idx++]; | 
 |       New = ::new (*Context) FormatAttr(Type, FormatIdx, FirstArg); | 
 |       break; | 
 |     } | 
 |          | 
 |     case Attr::Sentinel: { | 
 |       int sentinel = Record[Idx++]; | 
 |       int nullPos = Record[Idx++]; | 
 |       New = ::new (*Context) SentinelAttr(sentinel, nullPos); | 
 |       break; | 
 |     } | 
 |  | 
 |     SIMPLE_ATTR(GNUInline); | 
 |      | 
 |     case Attr::IBOutletKind: | 
 |       New = ::new (*Context) IBOutletAttr(); | 
 |       break; | 
 |  | 
 |     SIMPLE_ATTR(NoReturn); | 
 |     SIMPLE_ATTR(NoThrow); | 
 |     SIMPLE_ATTR(Nodebug); | 
 |     SIMPLE_ATTR(Noinline); | 
 |      | 
 |     case Attr::NonNull: { | 
 |       unsigned Size = Record[Idx++]; | 
 |       llvm::SmallVector<unsigned, 16> ArgNums; | 
 |       ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size); | 
 |       Idx += Size; | 
 |       New = ::new (*Context) NonNullAttr(&ArgNums[0], Size); | 
 |       break; | 
 |     } | 
 |  | 
 |     SIMPLE_ATTR(ObjCException); | 
 |     SIMPLE_ATTR(ObjCNSObject); | 
 |     SIMPLE_ATTR(CFReturnsRetained); | 
 |     SIMPLE_ATTR(NSReturnsRetained); | 
 |     SIMPLE_ATTR(Overloadable); | 
 |     UNSIGNED_ATTR(Packed); | 
 |     SIMPLE_ATTR(Pure); | 
 |     UNSIGNED_ATTR(Regparm); | 
 |     STRING_ATTR(Section); | 
 |     SIMPLE_ATTR(StdCall); | 
 |     SIMPLE_ATTR(TransparentUnion); | 
 |     SIMPLE_ATTR(Unavailable); | 
 |     SIMPLE_ATTR(Unused); | 
 |     SIMPLE_ATTR(Used); | 
 |      | 
 |     case Attr::Visibility: | 
 |       New = ::new (*Context) VisibilityAttr( | 
 |                               (VisibilityAttr::VisibilityTypes)Record[Idx++]); | 
 |       break; | 
 |  | 
 |     SIMPLE_ATTR(WarnUnusedResult); | 
 |     SIMPLE_ATTR(Weak); | 
 |     SIMPLE_ATTR(WeakImport); | 
 |     } | 
 |  | 
 |     assert(New && "Unable to decode attribute?"); | 
 |     New->setInherited(IsInherited); | 
 |     New->setNext(Attrs); | 
 |     Attrs = New; | 
 |   } | 
 | #undef UNSIGNED_ATTR | 
 | #undef STRING_ATTR | 
 | #undef SIMPLE_ATTR | 
 |  | 
 |   // The list of attributes was built backwards. Reverse the list | 
 |   // before returning it. | 
 |   Attr *PrevAttr = 0, *NextAttr = 0; | 
 |   while (Attrs) { | 
 |     NextAttr = Attrs->getNext(); | 
 |     Attrs->setNext(PrevAttr); | 
 |     PrevAttr = Attrs; | 
 |     Attrs = NextAttr; | 
 |   } | 
 |  | 
 |   return PrevAttr; | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // PCHReader Implementation | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | /// \brief Note that we have loaded the declaration with the given | 
 | /// Index. | 
 | ///  | 
 | /// This routine notes that this declaration has already been loaded, | 
 | /// so that future GetDecl calls will return this declaration rather | 
 | /// than trying to load a new declaration. | 
 | inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) { | 
 |   assert(!DeclsLoaded[Index] && "Decl loaded twice?"); | 
 |   DeclsLoaded[Index] = D; | 
 | } | 
 |  | 
 |  | 
 | /// \brief Determine whether the consumer will be interested in seeing | 
 | /// this declaration (via HandleTopLevelDecl). | 
 | /// | 
 | /// This routine should return true for anything that might affect | 
 | /// code generation, e.g., inline function definitions, Objective-C | 
 | /// declarations with metadata, etc. | 
 | static bool isConsumerInterestedIn(Decl *D) { | 
 |   if (VarDecl *Var = dyn_cast<VarDecl>(D)) | 
 |     return Var->isFileVarDecl() && Var->getInit(); | 
 |   if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) | 
 |     return Func->isThisDeclarationADefinition(); | 
 |   return isa<ObjCProtocolDecl>(D); | 
 | } | 
 |  | 
 | /// \brief Read the declaration at the given offset from the PCH file. | 
 | Decl *PCHReader::ReadDeclRecord(uint64_t Offset, unsigned Index) { | 
 |   // Keep track of where we are in the stream, then jump back there | 
 |   // after reading this declaration. | 
 |   SavedStreamPosition SavedPosition(DeclsCursor); | 
 |  | 
 |   DeclsCursor.JumpToBit(Offset); | 
 |   RecordData Record; | 
 |   unsigned Code = DeclsCursor.ReadCode(); | 
 |   unsigned Idx = 0; | 
 |   PCHDeclReader Reader(*this, Record, Idx); | 
 |  | 
 |   Decl *D = 0; | 
 |   switch ((pch::DeclCode)DeclsCursor.ReadRecord(Code, Record)) { | 
 |   case pch::DECL_ATTR: | 
 |   case pch::DECL_CONTEXT_LEXICAL: | 
 |   case pch::DECL_CONTEXT_VISIBLE: | 
 |     assert(false && "Record cannot be de-serialized with ReadDeclRecord"); | 
 |     break; | 
 |   case pch::DECL_TRANSLATION_UNIT: | 
 |     assert(Index == 0 && "Translation unit must be at index 0"); | 
 |     D = Context->getTranslationUnitDecl(); | 
 |     break; | 
 |   case pch::DECL_TYPEDEF: | 
 |     D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, QualType()); | 
 |     break; | 
 |   case pch::DECL_ENUM: | 
 |     D = EnumDecl::Create(*Context, 0, SourceLocation(), 0, 0); | 
 |     break; | 
 |   case pch::DECL_RECORD: | 
 |     D = RecordDecl::Create(*Context, TagDecl::TK_struct, 0, SourceLocation(), | 
 |                            0, 0); | 
 |     break; | 
 |   case pch::DECL_ENUM_CONSTANT: | 
 |     D = EnumConstantDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), | 
 |                                  0, llvm::APSInt()); | 
 |     break; | 
 |   case pch::DECL_FUNCTION: | 
 |     D = FunctionDecl::Create(*Context, 0, SourceLocation(), DeclarationName(),  | 
 |                              QualType()); | 
 |     break; | 
 |   case pch::DECL_OBJC_METHOD: | 
 |     D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(),  | 
 |                                Selector(), QualType(), 0); | 
 |     break; | 
 |   case pch::DECL_OBJC_INTERFACE: | 
 |     D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0); | 
 |     break; | 
 |   case pch::DECL_OBJC_IVAR: | 
 |     D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), | 
 |                              ObjCIvarDecl::None); | 
 |     break; | 
 |   case pch::DECL_OBJC_PROTOCOL: | 
 |     D = ObjCProtocolDecl::Create(*Context, 0, SourceLocation(), 0); | 
 |     break; | 
 |   case pch::DECL_OBJC_AT_DEFS_FIELD: | 
 |     D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), 0,  | 
 |                                     QualType(), 0); | 
 |     break; | 
 |   case pch::DECL_OBJC_CLASS: | 
 |     D = ObjCClassDecl::Create(*Context, 0, SourceLocation()); | 
 |     break; | 
 |   case pch::DECL_OBJC_FORWARD_PROTOCOL: | 
 |     D = ObjCForwardProtocolDecl::Create(*Context, 0, SourceLocation()); | 
 |     break; | 
 |   case pch::DECL_OBJC_CATEGORY: | 
 |     D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(), 0); | 
 |     break; | 
 |   case pch::DECL_OBJC_CATEGORY_IMPL: | 
 |     D = ObjCCategoryImplDecl::Create(*Context, 0, SourceLocation(), 0, 0); | 
 |     break; | 
 |   case pch::DECL_OBJC_IMPLEMENTATION: | 
 |     D = ObjCImplementationDecl::Create(*Context, 0, SourceLocation(), 0, 0); | 
 |     break; | 
 |   case pch::DECL_OBJC_COMPATIBLE_ALIAS: | 
 |     D = ObjCCompatibleAliasDecl::Create(*Context, 0, SourceLocation(), 0, 0); | 
 |     break; | 
 |   case pch::DECL_OBJC_PROPERTY: | 
 |     D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, QualType()); | 
 |     break; | 
 |   case pch::DECL_OBJC_PROPERTY_IMPL: | 
 |     D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(), | 
 |                                      SourceLocation(), 0,  | 
 |                                      ObjCPropertyImplDecl::Dynamic, 0); | 
 |     break; | 
 |   case pch::DECL_FIELD: | 
 |     D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,  | 
 |                           false); | 
 |     break; | 
 |   case pch::DECL_VAR: | 
 |     D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), | 
 |                         VarDecl::None, SourceLocation()); | 
 |     break; | 
 |  | 
 |   case pch::DECL_IMPLICIT_PARAM: | 
 |     D = ImplicitParamDecl::Create(*Context, 0, SourceLocation(), 0, QualType()); | 
 |     break; | 
 |  | 
 |   case pch::DECL_PARM_VAR: | 
 |     D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(),  | 
 |                             VarDecl::None, 0); | 
 |     break; | 
 |   case pch::DECL_ORIGINAL_PARM_VAR: | 
 |     D = OriginalParmVarDecl::Create(*Context, 0, SourceLocation(), 0, | 
 |                                     QualType(), QualType(), VarDecl::None, 0); | 
 |     break; | 
 |   case pch::DECL_FILE_SCOPE_ASM: | 
 |     D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0); | 
 |     break; | 
 |   case pch::DECL_BLOCK: | 
 |     D = BlockDecl::Create(*Context, 0, SourceLocation()); | 
 |     break; | 
 |   } | 
 |  | 
 |   assert(D && "Unknown declaration reading PCH file"); | 
 |   LoadedDecl(Index, D); | 
 |   Reader.Visit(D); | 
 |  | 
 |   // If this declaration is also a declaration context, get the | 
 |   // offsets for its tables of lexical and visible declarations. | 
 |   if (DeclContext *DC = dyn_cast<DeclContext>(D)) { | 
 |     std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC); | 
 |     if (Offsets.first || Offsets.second) { | 
 |       DC->setHasExternalLexicalStorage(Offsets.first != 0); | 
 |       DC->setHasExternalVisibleStorage(Offsets.second != 0); | 
 |       DeclContextOffsets[DC] = Offsets; | 
 |     } | 
 |   } | 
 |   assert(Idx == Record.size()); | 
 |  | 
 |   // If we have deserialized a declaration that has a definition the | 
 |   // AST consumer might need to know about, notify the consumer | 
 |   // about that definition now or queue it for later. | 
 |   if (isConsumerInterestedIn(D)) { | 
 |     if (Consumer) { | 
 |       DeclGroupRef DG(D); | 
 |       Consumer->HandleTopLevelDecl(DG); | 
 |     } else { | 
 |       InterestingDecls.push_back(D); | 
 |     } | 
 |   } | 
 |  | 
 |   return D; | 
 | } | 
 |  |