//===--- 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/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" using namespace clang; //===----------------------------------------------------------------------===// // Declaration deserialization //===----------------------------------------------------------------------===// namespace { class PCHDeclReader : public DeclVisitor { 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 VisitNamespaceDecl(NamespaceDecl *D); void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitTypeDecl(TypeDecl *TD); void VisitTypedefDecl(TypedefDecl *TD); void VisitUnresolvedUsingTypename(UnresolvedUsingTypenameDecl *D); void VisitTagDecl(TagDecl *TD); void VisitEnumDecl(EnumDecl *ED); void VisitRecordDecl(RecordDecl *RD); void VisitCXXRecordDecl(CXXRecordDecl *D); void VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D); void VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D); void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); void VisitValueDecl(ValueDecl *VD); void VisitEnumConstantDecl(EnumConstantDecl *ECD); void VisitUnresolvedUsingValue(UnresolvedUsingValueDecl *D); void VisitDeclaratorDecl(DeclaratorDecl *DD); void VisitFunctionDecl(FunctionDecl *FD); void VisitCXXMethodDecl(CXXMethodDecl *D); void VisitCXXConstructorDecl(CXXConstructorDecl *D); void VisitCXXDestructorDecl(CXXDestructorDecl *D); void VisitCXXConversionDecl(CXXConversionDecl *D); void VisitFieldDecl(FieldDecl *FD); void VisitVarDecl(VarDecl *VD); void VisitImplicitParamDecl(ImplicitParamDecl *PD); void VisitParmVarDecl(ParmVarDecl *PD); void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); void VisitTemplateDecl(TemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); void visitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); void VisitUsing(UsingDecl *D); void VisitUsingShadow(UsingShadowDecl *D); void VisitLinkageSpecDecl(LinkageSpecDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); void VisitFriendTemplateDecl(FriendTemplateDecl *D); void VisitStaticAssertDecl(StaticAssertDecl *D); void VisitBlockDecl(BlockDecl *BD); std::pair VisitDeclContext(DeclContext *DC); // FIXME: Reorder according to DeclNodes.def? 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(Reader.GetDecl(Record[Idx++]))); D->setLexicalDeclContext( cast_or_null(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->setUsed(Record[Idx++]); D->setAccess((AccessSpecifier)Record[Idx++]); D->setPCHLevel(Record[Idx++] + 1); } void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { VisitDecl(TU); TU->setAnonymousNamespace( cast_or_null(Reader.GetDecl(Record[Idx++]))); } 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); uint64_t TypeData = Record[Idx++]; TD->setTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); TD->setTypeForDecl(Reader.GetType(TypeData).getTypePtr()); } void PCHDeclReader::VisitTagDecl(TagDecl *TD) { VisitTypeDecl(TD); TD->setPreviousDeclaration( cast_or_null(Reader.GetDecl(Record[Idx++]))); TD->setTagKind((TagDecl::TagKind)Record[Idx++]); TD->setDefinition(Record[Idx++]); TD->setEmbeddedInDeclarator(Record[Idx++]); TD->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); TD->setTagKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); // FIXME: maybe read optional qualifier and its range. TD->setTypedefForAnonDecl( cast_or_null(Reader.GetDecl(Record[Idx++]))); } void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) { VisitTagDecl(ED); ED->setIntegerType(Reader.GetType(Record[Idx++])); ED->setPromotionType(Reader.GetType(Record[Idx++])); ED->setNumPositiveBits(Record[Idx++]); ED->setNumNegativeBits(Record[Idx++]); // FIXME: C++ InstantiatedFrom } void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) { VisitTagDecl(RD); RD->setHasFlexibleArrayMember(Record[Idx++]); RD->setAnonymousStructOrUnion(Record[Idx++]); RD->setHasObjectMember(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::VisitDeclaratorDecl(DeclaratorDecl *DD) { VisitValueDecl(DD); TypeSourceInfo *TInfo = Reader.GetTypeSourceInfo(Record, Idx); if (TInfo) DD->setTypeSourceInfo(TInfo); // FIXME: read optional qualifier and its range. } void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { VisitDeclaratorDecl(FD); if (Record[Idx++]) FD->setLazyBody(Reader.getDeclsCursor().GetCurrentBitNo()); FD->setPreviousDeclaration( cast_or_null(Reader.GetDecl(Record[Idx++]))); FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]); FD->setStorageClassAsWritten((FunctionDecl::StorageClass)Record[Idx++]); FD->setInlineSpecified(Record[Idx++]); FD->setVirtualAsWritten(Record[Idx++]); FD->setPure(Record[Idx++]); FD->setHasInheritedPrototype(Record[Idx++]); FD->setHasWrittenPrototype(Record[Idx++]); FD->setDeleted(Record[Idx++]); FD->setTrivial(Record[Idx++]); FD->setCopyAssignment(Record[Idx++]); FD->setHasImplicitReturnZero(Record[Idx++]); FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++])); // FIXME: C++ TemplateOrInstantiation // Read in the parameters. unsigned NumParams = Record[Idx++]; llvm::SmallVector Params; Params.reserve(NumParams); for (unsigned I = 0; I != NumParams; ++I) Params.push_back(cast(Reader.GetDecl(Record[Idx++]))); FD->setParams(Params.data(), NumParams); // FIXME: order this properly w.r.t. friendness // FIXME: this same thing needs to happen for function templates if (FD->isOverloadedOperator() && !FD->getDeclContext()->isRecord()) FD->setNonMemberOperator(); } 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(Reader.GetDecl(Record[Idx++]))); MD->setCmdDecl(cast(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->setNumSelectorArgs(unsigned(Record[Idx++])); MD->setResultType(Reader.GetType(Record[Idx++])); MD->setResultTypeSourceInfo(Reader.GetTypeSourceInfo(Record, Idx)); MD->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); unsigned NumParams = Record[Idx++]; llvm::SmallVector Params; Params.reserve(NumParams); for (unsigned I = 0; I != NumParams; ++I) Params.push_back(cast(Reader.GetDecl(Record[Idx++]))); MD->setMethodParams(*Reader.getContext(), Params.data(), NumParams, NumParams); } void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) { VisitNamedDecl(CD); SourceLocation A = SourceLocation::getFromRawEncoding(Record[Idx++]); SourceLocation B = SourceLocation::getFromRawEncoding(Record[Idx++]); CD->setAtEndRange(SourceRange(A, B)); } void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { VisitObjCContainerDecl(ID); ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr()); ID->setSuperClass(cast_or_null (Reader.GetDecl(Record[Idx++]))); unsigned NumProtocols = Record[Idx++]; llvm::SmallVector Protocols; Protocols.reserve(NumProtocols); for (unsigned I = 0; I != NumProtocols; ++I) Protocols.push_back(cast(Reader.GetDecl(Record[Idx++]))); llvm::SmallVector ProtoLocs; ProtoLocs.reserve(NumProtocols); for (unsigned I = 0; I != NumProtocols; ++I) ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(), *Reader.getContext()); unsigned NumIvars = Record[Idx++]; llvm::SmallVector IVars; IVars.reserve(NumIvars); for (unsigned I = 0; I != NumIvars; ++I) IVars.push_back(cast(Reader.GetDecl(Record[Idx++]))); ID->setCategoryList( cast_or_null(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->setLocEnd(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 ProtoRefs; ProtoRefs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) ProtoRefs.push_back(cast(Reader.GetDecl(Record[Idx++]))); llvm::SmallVector ProtoLocs; ProtoLocs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), *Reader.getContext()); } void PCHDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) { VisitFieldDecl(FD); } void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) { VisitDecl(CD); unsigned NumClassRefs = Record[Idx++]; llvm::SmallVector ClassRefs; ClassRefs.reserve(NumClassRefs); for (unsigned I = 0; I != NumClassRefs; ++I) ClassRefs.push_back(cast(Reader.GetDecl(Record[Idx++]))); llvm::SmallVector SLocs; SLocs.reserve(NumClassRefs); for (unsigned I = 0; I != NumClassRefs; ++I) SLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(), NumClassRefs); } void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) { VisitDecl(FPD); unsigned NumProtoRefs = Record[Idx++]; llvm::SmallVector ProtoRefs; ProtoRefs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) ProtoRefs.push_back(cast(Reader.GetDecl(Record[Idx++]))); llvm::SmallVector ProtoLocs; ProtoLocs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), *Reader.getContext()); } void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) { VisitObjCContainerDecl(CD); CD->setClassInterface(cast(Reader.GetDecl(Record[Idx++]))); unsigned NumProtoRefs = Record[Idx++]; llvm::SmallVector ProtoRefs; ProtoRefs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) ProtoRefs.push_back(cast(Reader.GetDecl(Record[Idx++]))); llvm::SmallVector ProtoLocs; ProtoLocs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++])); CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), *Reader.getContext()); CD->setNextClassCategory(cast_or_null(Reader.GetDecl(Record[Idx++]))); CD->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); CD->setCategoryNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) { VisitNamedDecl(CAD); CAD->setClassInterface(cast(Reader.GetDecl(Record[Idx++]))); } void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { VisitNamedDecl(D); D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); 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(Reader.GetDecl(Record[Idx++]))); D->setSetterMethodDecl( cast_or_null(Reader.GetDecl(Record[Idx++]))); D->setPropertyIvarDecl( cast_or_null(Reader.GetDecl(Record[Idx++]))); } void PCHDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) { VisitObjCContainerDecl(D); D->setClassInterface( cast_or_null(Reader.GetDecl(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(Reader.GetDecl(Record[Idx++]))); // FIXME. Add reading of IvarInitializers and NumIvarInitializers. } void PCHDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { VisitDecl(D); D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); D->setPropertyDecl( cast_or_null(Reader.GetDecl(Record[Idx++]))); D->setPropertyIvarDecl( cast_or_null(Reader.GetDecl(Record[Idx++]))); // FIXME. read GetterCXXConstructor and SetterCXXAssignment } void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) { VisitDeclaratorDecl(FD); FD->setMutable(Record[Idx++]); if (Record[Idx++]) FD->setBitWidth(Reader.ReadDeclExpr()); } void PCHDeclReader::VisitVarDecl(VarDecl *VD) { VisitDeclaratorDecl(VD); VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]); VD->setStorageClassAsWritten((VarDecl::StorageClass)Record[Idx++]); VD->setThreadSpecified(Record[Idx++]); VD->setCXXDirectInitializer(Record[Idx++]); VD->setDeclaredInCondition(Record[Idx++]); VD->setExceptionVariable(Record[Idx++]); VD->setNRVOVariable(Record[Idx++]); VD->setPreviousDeclaration( cast_or_null(Reader.GetDecl(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++]); PD->setHasInheritedDefaultArg(Record[Idx++]); } void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) { VisitDecl(AD); AD->setAsmString(cast(Reader.ReadDeclExpr())); } void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) { VisitDecl(BD); BD->setBody(cast_or_null(Reader.ReadDeclStmt())); unsigned NumParams = Record[Idx++]; llvm::SmallVector Params; Params.reserve(NumParams); for (unsigned I = 0; I != NumParams; ++I) Params.push_back(cast(Reader.GetDecl(Record[Idx++]))); BD->setParams(Params.data(), NumParams); } void PCHDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) { VisitDecl(D); D->setLanguage((LinkageSpecDecl::LanguageIDs)Record[Idx++]); D->setHasBraces(Record[Idx++]); } void PCHDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { VisitNamedDecl(D); D->setLBracLoc(Reader.ReadSourceLocation(Record, Idx)); D->setRBracLoc(Reader.ReadSourceLocation(Record, Idx)); D->setNextNamespace( cast_or_null(Reader.GetDecl(Record[Idx++]))); // Only read one reference--the original or anonymous namespace. bool IsOriginal = Record[Idx++]; if (IsOriginal) D->setAnonymousNamespace( cast_or_null(Reader.GetDecl(Record[Idx++]))); else D->setOriginalNamespace( cast_or_null(Reader.GetDecl(Record[Idx++]))); } void PCHDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { VisitNamedDecl(D); D->setAliasLoc(Reader.ReadSourceLocation(Record, Idx)); D->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); D->setTargetNameLoc(Reader.ReadSourceLocation(Record, Idx)); D->setAliasedNamespace(cast(Reader.GetDecl(Record[Idx++]))); } void PCHDeclReader::VisitUsing(UsingDecl *D) { VisitNamedDecl(D); D->setUsingLocation(Reader.ReadSourceLocation(Record, Idx)); D->setNestedNameRange(Reader.ReadSourceRange(Record, Idx)); D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx)); // FIXME: It would probably be more efficient to read these into a vector // and then re-cosntruct the shadow decl set over that vector since it // would avoid existence checks. unsigned NumShadows = Record[Idx++]; for(unsigned I = 0; I != NumShadows; ++I) { D->addShadowDecl(cast(Reader.GetDecl(Record[Idx++]))); } D->setTypeName(Record[Idx++]); } void PCHDeclReader::VisitUsingShadow(UsingShadowDecl *D) { VisitNamedDecl(D); D->setTargetDecl(cast(Reader.GetDecl(Record[Idx++]))); D->setUsingDecl(cast(Reader.GetDecl(Record[Idx++]))); } void PCHDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { VisitNamedDecl(D); D->setNamespaceKeyLocation(Reader.ReadSourceLocation(Record, Idx)); D->setQualifierRange(Reader.ReadSourceRange(Record, Idx)); D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx)); D->setIdentLocation(Reader.ReadSourceLocation(Record, Idx)); D->setNominatedNamespace(cast(Reader.GetDecl(Record[Idx++]))); D->setCommonAncestor(cast_or_null( Reader.GetDecl(Record[Idx++]))); } void PCHDeclReader::VisitUnresolvedUsingValue(UnresolvedUsingValueDecl *D) { VisitValueDecl(D); D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx)); D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx)); D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx)); } void PCHDeclReader::VisitUnresolvedUsingTypename( UnresolvedUsingTypenameDecl *D) { VisitTypeDecl(D); D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx)); D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx)); D->setTypenameLoc(Reader.ReadSourceLocation(Record, Idx)); D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx)); } void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { // assert(false && "cannot read CXXRecordDecl"); VisitRecordDecl(D); } void PCHDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { // assert(false && "cannot read CXXMethodDecl"); VisitFunctionDecl(D); } void PCHDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { // assert(false && "cannot read CXXConstructorDecl"); VisitCXXMethodDecl(D); } void PCHDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { // assert(false && "cannot read CXXDestructorDecl"); VisitCXXMethodDecl(D); } void PCHDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { // assert(false && "cannot read CXXConversionDecl"); VisitCXXMethodDecl(D); } void PCHDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { assert(false && "cannot read FriendTemplateDecl"); } void PCHDeclReader::VisitTemplateDecl(TemplateDecl *D) { assert(false && "cannot read TemplateDecl"); } void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { assert(false && "cannot read ClassTemplateDecl"); } void PCHDeclReader::VisitClassTemplateSpecializationDecl( ClassTemplateSpecializationDecl *D) { assert(false && "cannot read ClassTemplateSpecializationDecl"); } void PCHDeclReader::VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { assert(false && "cannot read ClassTemplatePartialSpecializationDecl"); } void PCHDeclReader::visitFunctionTemplateDecl(FunctionTemplateDecl *D) { assert(false && "cannot read FunctionTemplateDecl"); } void PCHDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { assert(false && "cannot read TemplateTypeParmDecl"); } void PCHDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { assert(false && "cannot read NonTypeTemplateParmDecl"); } void PCHDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { assert(false && "cannot read TemplateTemplateParmDecl"); } void PCHDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) { assert(false && "cannot read StaticAssertDecl"); } std::pair 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(*Context, 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) { default: assert(0 && "Unknown attribute!"); break; STRING_ATTR(Alias); SIMPLE_ATTR(AlignMac68k); UNSIGNED_ATTR(Aligned); SIMPLE_ATTR(AlwaysInline); SIMPLE_ATTR(AnalyzerNoReturn); STRING_ATTR(Annotate); STRING_ATTR(AsmLabel); SIMPLE_ATTR(BaseCheck); case Attr::Blocks: New = ::new (*Context) BlocksAttr( (BlocksAttr::BlocksAttrTypes)Record[Idx++]); break; SIMPLE_ATTR(CDecl); case Attr::Cleanup: New = ::new (*Context) CleanupAttr( cast(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); SIMPLE_ATTR(Final); case Attr::Format: { std::string Type = ReadString(Record, Idx); unsigned FormatIdx = Record[Idx++]; unsigned FirstArg = Record[Idx++]; New = ::new (*Context) FormatAttr(*Context, Type, FormatIdx, FirstArg); break; } case Attr::FormatArg: { unsigned FormatIdx = Record[Idx++]; New = ::new (*Context) FormatArgAttr(FormatIdx); break; } case Attr::Sentinel: { int sentinel = Record[Idx++]; int nullPos = Record[Idx++]; New = ::new (*Context) SentinelAttr(sentinel, nullPos); break; } SIMPLE_ATTR(GNUInline); SIMPLE_ATTR(Hiding); case Attr::IBActionKind: New = ::new (*Context) IBActionAttr(); break; case Attr::IBOutletKind: New = ::new (*Context) IBOutletAttr(); break; case Attr::IBOutletCollectionKind: { ObjCInterfaceDecl *D = cast_or_null(GetDecl(Record[Idx++])); New = ::new (*Context) IBOutletCollectionAttr(D); break; } SIMPLE_ATTR(Malloc); SIMPLE_ATTR(NoDebug); SIMPLE_ATTR(NoInline); SIMPLE_ATTR(NoReturn); SIMPLE_ATTR(NoThrow); case Attr::NonNull: { unsigned Size = Record[Idx++]; llvm::SmallVector ArgNums; ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size); Idx += Size; New = ::new (*Context) NonNullAttr(*Context, ArgNums.data(), Size); break; } case Attr::ReqdWorkGroupSize: { unsigned X = Record[Idx++]; unsigned Y = Record[Idx++]; unsigned Z = Record[Idx++]; New = ::new (*Context) ReqdWorkGroupSizeAttr(X, Y, Z); break; } SIMPLE_ATTR(ObjCException); SIMPLE_ATTR(ObjCNSObject); SIMPLE_ATTR(CFReturnsNotRetained); SIMPLE_ATTR(CFReturnsRetained); SIMPLE_ATTR(NSReturnsNotRetained); SIMPLE_ATTR(NSReturnsRetained); SIMPLE_ATTR(Overloadable); SIMPLE_ATTR(Override); SIMPLE_ATTR(Packed); UNSIGNED_ATTR(MaxFieldAlignment); SIMPLE_ATTR(Pure); UNSIGNED_ATTR(Regparm); STRING_ATTR(Section); SIMPLE_ATTR(StdCall); SIMPLE_ATTR(ThisCall); 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(WeakRef); 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 (isa(D)) return true; if (VarDecl *Var = dyn_cast(D)) return Var->isFileVarDecl() && Var->getInit(); if (FunctionDecl *Func = dyn_cast(D)) return Func->isThisDeclarationADefinition(); return isa(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); // Note that we are loading a declaration record. LoadingTypeOrDecl Loading(*this); 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, 0); break; case pch::DECL_ENUM: D = EnumDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(), 0); break; case pch::DECL_RECORD: D = RecordDecl::Create(*Context, TTK_Struct, 0, SourceLocation(), 0, SourceLocation(), 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(), 0); break; case pch::DECL_LINKAGE_SPEC: D = LinkageSpecDecl::Create(*Context, 0, SourceLocation(), (LinkageSpecDecl::LanguageIDs)0, false); break; case pch::DECL_NAMESPACE: D = NamespaceDecl::Create(*Context, 0, SourceLocation(), 0); break; case pch::DECL_NAMESPACE_ALIAS: D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0, SourceRange(), 0, SourceLocation(), 0); break; case pch::DECL_USING: D = UsingDecl::Create(*Context, 0, SourceLocation(), SourceRange(), SourceLocation(), 0, DeclarationName(), false); break; case pch::DECL_USING_SHADOW: D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0); break; case pch::DECL_USING_DIRECTIVE: D = UsingDirectiveDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), SourceRange(), 0, SourceLocation(), 0, 0); break; case pch::DECL_UNRESOLVED_USING_VALUE: D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(), SourceRange(), 0, SourceLocation(), DeclarationName()); break; case pch::DECL_UNRESOLVED_USING_TYPENAME: D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), SourceRange(), 0, SourceLocation(), DeclarationName()); break; case pch::DECL_CXX_RECORD: D = CXXRecordDecl::Create(*Context, TTK_Struct, 0, SourceLocation(), 0, SourceLocation(), 0); break; case pch::DECL_CXX_METHOD: D = CXXMethodDecl::Create(*Context, 0, SourceLocation(), DeclarationName(), QualType(), 0); break; case pch::DECL_CXX_CONSTRUCTOR: D = CXXConstructorDecl::Create(*Context, Decl::EmptyShell()); break; case pch::DECL_CXX_DESTRUCTOR: D = CXXDestructorDecl::Create(*Context, Decl::EmptyShell()); break; case pch::DECL_CXX_CONVERSION: D = CXXConversionDecl::Create(*Context, Decl::EmptyShell()); break; case pch::DECL_FRIEND: assert(false && "cannot read FriendDecl"); break; case pch::DECL_FRIEND_TEMPLATE: assert(false && "cannot read FriendTemplateDecl"); break; case pch::DECL_TEMPLATE: // FIXME: Should TemplateDecl be ABSTRACT_DECL??? assert(false && "TemplateDecl should be abstract!"); break; case pch::DECL_CLASS_TEMPLATE: assert(false && "cannot read ClassTemplateDecl"); break; case pch::DECL_CLASS_TEMPLATE_SPECIALIZATION: assert(false && "cannot read ClasstemplateSpecializationDecl"); break; case pch::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION: assert(false && "cannot read ClassTemplatePartialSpecializationDecl"); break; case pch::DECL_FUNCTION_TEMPLATE: assert(false && "cannot read FunctionTemplateDecl"); break; case pch::DECL_TEMPLATE_TYPE_PARM: assert(false && "cannot read TemplateTypeParmDecl"); break; case pch::DECL_NON_TYPE_TEMPLATE_PARM: assert(false && "cannot read NonTypeTemplateParmDecl"); break; case pch::DECL_TEMPLATE_TEMPLATE_PARM: assert(false && "cannot read TemplateTemplateParmDecl"); break; case pch::DECL_STATIC_ASSERT: assert(false && "cannot read StaticAssertDecl"); break; case pch::DECL_OBJC_METHOD: D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(), Selector(), QualType(), 0, 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(), 0, 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(), SourceLocation(), 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, SourceLocation(), 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, 0, false); break; case pch::DECL_VAR: D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, VarDecl::None, VarDecl::None); 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(), 0, VarDecl::None, 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(D)) { std::pair 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; }