forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			696 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			696 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===--- 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;
 | |
|     }
 | |
| 
 | |
|     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(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;
 | |
| }
 | |
| 
 |