diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp | 427 |
1 files changed, 301 insertions, 126 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp index 707a924..0853415 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTReaderDecl.cpp @@ -119,12 +119,16 @@ namespace clang { } void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update); - void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data); + void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data, + const CXXRecordDecl *D); void MergeDefinitionData(CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&NewDD); void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data); void MergeDefinitionData(ObjCInterfaceDecl *D, struct ObjCInterfaceDecl::DefinitionData &&NewDD); + void ReadObjCDefinitionData(struct ObjCProtocolDecl::DefinitionData &Data); + void MergeDefinitionData(ObjCProtocolDecl *D, + struct ObjCProtocolDecl::DefinitionData &&NewDD); static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, @@ -215,6 +219,30 @@ namespace clang { TypedefNameForLinkage(nullptr), HasPendingBody(false), IsDeclMarkedUsed(false) {} + template <typename T> static + void AddLazySpecializations(T *D, + SmallVectorImpl<serialization::DeclID>& IDs) { + if (IDs.empty()) + return; + + // FIXME: We should avoid this pattern of getting the ASTContext. + ASTContext &C = D->getASTContext(); + + auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations; + + if (auto &Old = LazySpecializations) { + IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); + std::sort(IDs.begin(), IDs.end()); + IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); + } + + auto *Result = new (C) serialization::DeclID[1 + IDs.size()]; + *Result = IDs.size(); + std::copy(IDs.begin(), IDs.end(), Result + 1); + + LazySpecializations = Result; + } + template <typename DeclT> static Decl *getMostRecentDeclImpl(Redeclarable<DeclT> *D); static Decl *getMostRecentDeclImpl(...); @@ -240,9 +268,10 @@ namespace clang { /// \brief Determine whether this declaration has a pending body. bool hasPendingBody() const { return HasPendingBody; } + void ReadFunctionDefinition(FunctionDecl *FD); void Visit(Decl *D); - void UpdateDecl(Decl *D); + void UpdateDecl(Decl *D, llvm::SmallVectorImpl<serialization::DeclID>&); static void setNextObjCCategory(ObjCCategoryDecl *Cat, ObjCCategoryDecl *Next) { @@ -292,6 +321,7 @@ namespace clang { void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); void VisitDeclaratorDecl(DeclaratorDecl *DD); void VisitFunctionDecl(FunctionDecl *FD); + void VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *GD); void VisitCXXMethodDecl(CXXMethodDecl *D); void VisitCXXConstructorDecl(CXXConstructorDecl *D); void VisitCXXDestructorDecl(CXXDestructorDecl *D); @@ -421,6 +451,19 @@ uint64_t ASTDeclReader::GetCurrentCursorOffset() { return Loc.F->DeclsCursor.GetCurrentBitNo() + Loc.F->GlobalBitOffset; } +void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) { + if (Record.readInt()) + Reader.BodySource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile; + if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { + CD->NumCtorInitializers = Record.readInt(); + if (CD->NumCtorInitializers) + CD->CtorInitializers = ReadGlobalOffset(); + } + // Store the offset of the body so we can lazily load it later. + Reader.PendingBodies[FD] = GetCurrentCursorOffset(); + HasPendingBody = true; +} + void ASTDeclReader::Visit(Decl *D) { DeclVisitor<ASTDeclReader, void>::Visit(D); @@ -457,15 +500,8 @@ void ASTDeclReader::Visit(Decl *D) { // We only read it if FD doesn't already have a body (e.g., from another // module). // FIXME: Can we diagnose ODR violations somehow? - if (Record.readInt()) { - if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { - CD->NumCtorInitializers = Record.readInt(); - if (CD->NumCtorInitializers) - CD->CtorInitializers = ReadGlobalOffset(); - } - Reader.PendingBodies[FD] = GetCurrentCursorOffset(); - HasPendingBody = true; - } + if (Record.readInt()) + ReadFunctionDefinition(FD); } } @@ -513,32 +549,32 @@ void ASTDeclReader::VisitDecl(Decl *D) { D->setTopLevelDeclInObjCContainer(Record.readInt()); D->setAccess((AccessSpecifier)Record.readInt()); D->FromASTFile = true; - D->setModulePrivate(Record.readInt()); - D->Hidden = D->isModulePrivate(); + bool ModulePrivate = Record.readInt(); // Determine whether this declaration is part of a (sub)module. If so, it // may not yet be visible. if (unsigned SubmoduleID = readSubmoduleID()) { // Store the owning submodule ID in the declaration. + D->setModuleOwnershipKind( + ModulePrivate ? Decl::ModuleOwnershipKind::ModulePrivate + : Decl::ModuleOwnershipKind::VisibleWhenImported); D->setOwningModuleID(SubmoduleID); - if (D->Hidden) { - // Module-private declarations are never visible, so there is no work to do. + if (ModulePrivate) { + // Module-private declarations are never visible, so there is no work to + // do. } else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) { // If local visibility is being tracked, this declaration will become - // hidden and visible as the owning module does. Inform Sema that this - // declaration might not be visible. - D->Hidden = true; + // hidden and visible as the owning module does. } else if (Module *Owner = Reader.getSubmodule(SubmoduleID)) { - if (Owner->NameVisibility != Module::AllVisible) { - // The owning module is not visible. Mark this declaration as hidden. - D->Hidden = true; - - // Note that this declaration was hidden because its owning module is - // not yet visible. + // Mark the declaration as visible when its owning module becomes visible. + if (Owner->NameVisibility == Module::AllVisible) + D->setVisibleDespiteOwningModule(); + else Reader.HiddenNamesMap[Owner].push_back(D); - } } + } else if (ModulePrivate) { + D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate); } } @@ -592,6 +628,11 @@ ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { TD->setModedTypeSourceInfo(TInfo, modedT); } else TD->setTypeSourceInfo(TInfo); + // Read and discard the declaration for which this is a typedef name for + // linkage, if it exists. We cannot rely on our type to pull in this decl, + // because it might have been merged with a type from another module and + // thus might not refer to our version of the declaration. + ReadDecl(); return Redecl; } @@ -738,6 +779,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->SClass = (StorageClass)Record.readInt(); FD->IsInline = Record.readInt(); FD->IsInlineSpecified = Record.readInt(); + FD->IsExplicitSpecified = Record.readInt(); FD->IsVirtualAsWritten = Record.readInt(); FD->IsPure = Record.readInt(); FD->HasInheritedPrototype = Record.readInt(); @@ -1032,18 +1074,8 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { IVD->setSynthesize(synth); } -void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { - RedeclarableResult Redecl = VisitRedeclarable(PD); - VisitObjCContainerDecl(PD); - mergeRedeclarable(PD, Redecl); - - if (Record.readInt()) { - // Read the definition. - PD->allocateDefinitionData(); - - // Set the definition data of the canonical declaration, so other - // redeclarations will see it. - PD->getCanonicalDecl()->Data = PD->Data; +void ASTDeclReader::ReadObjCDefinitionData( + struct ObjCProtocolDecl::DefinitionData &Data) { unsigned NumProtoRefs = Record.readInt(); SmallVector<ObjCProtocolDecl *, 16> ProtoRefs; @@ -1054,9 +1086,37 @@ void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { ProtoLocs.reserve(NumProtoRefs); for (unsigned I = 0; I != NumProtoRefs; ++I) ProtoLocs.push_back(ReadSourceLocation()); - PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), - Reader.getContext()); + Data.ReferencedProtocols.set(ProtoRefs.data(), NumProtoRefs, + ProtoLocs.data(), Reader.getContext()); +} + +void ASTDeclReader::MergeDefinitionData(ObjCProtocolDecl *D, + struct ObjCProtocolDecl::DefinitionData &&NewDD) { + // FIXME: odr checking? +} + +void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { + RedeclarableResult Redecl = VisitRedeclarable(PD); + VisitObjCContainerDecl(PD); + mergeRedeclarable(PD, Redecl); + + if (Record.readInt()) { + // Read the definition. + PD->allocateDefinitionData(); + + ReadObjCDefinitionData(PD->data()); + ObjCProtocolDecl *Canon = PD->getCanonicalDecl(); + if (Canon->Data.getPointer()) { + // If we already have a definition, keep the definition invariant and + // merge the data. + MergeDefinitionData(Canon, std::move(PD->data())); + PD->Data = Canon->Data; + } else { + // Set the definition data of the canonical declaration, so other + // redeclarations will see it. + PD->getCanonicalDecl()->Data = PD->Data; + } // Note that we have deserialized a definition. Reader.PendingDefinitions.insert(PD); } else { @@ -1112,8 +1172,12 @@ void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { (ObjCPropertyDecl::PropertyAttributeKind)Record.readInt()); D->setPropertyImplementation( (ObjCPropertyDecl::PropertyControl)Record.readInt()); - D->setGetterName(Record.readDeclarationName().getObjCSelector()); - D->setSetterName(Record.readDeclarationName().getObjCSelector()); + DeclarationName GetterName = Record.readDeclarationName(); + SourceLocation GetterLoc = ReadSourceLocation(); + D->setGetterName(GetterName.getObjCSelector(), GetterLoc); + DeclarationName SetterName = Record.readDeclarationName(); + SourceLocation SetterLoc = ReadSourceLocation(); + D->setSetterName(SetterName.getObjCSelector(), SetterLoc); D->setGetterMethodDecl(ReadDeclAs<ObjCMethodDecl>()); D->setSetterMethodDecl(ReadDeclAs<ObjCMethodDecl>()); D->setPropertyIvarDecl(ReadDeclAs<ObjCIvarDecl>()); @@ -1126,7 +1190,6 @@ void ASTDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) { void ASTDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { VisitObjCImplDecl(D); - D->setIdentifier(Record.getIdentifierInfo()); D->CategoryNameLoc = ReadSourceLocation(); } @@ -1211,6 +1274,7 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { VD->NonParmVarDeclBits.IsConstexpr = Record.readInt(); VD->NonParmVarDeclBits.IsInitCapture = Record.readInt(); VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt(); + VD->NonParmVarDeclBits.ImplicitParamKind = Record.readInt(); } Linkage VarLinkage = Linkage(Record.readInt()); VD->setCachedLinkage(VarLinkage); @@ -1473,7 +1537,7 @@ void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( } void ASTDeclReader::ReadCXXDefinitionData( - struct CXXRecordDecl::DefinitionData &Data) { + struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D) { // Note: the caller has deserialized the IsLambda bit already. Data.UserDeclaredConstructor = Record.readInt(); Data.UserDeclaredSpecialMembers = Record.readInt(); @@ -1495,9 +1559,11 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.HasUninitializedFields = Record.readInt(); Data.HasInheritedConstructor = Record.readInt(); Data.HasInheritedAssignment = Record.readInt(); + Data.NeedOverloadResolutionForCopyConstructor = Record.readInt(); Data.NeedOverloadResolutionForMoveConstructor = Record.readInt(); Data.NeedOverloadResolutionForMoveAssignment = Record.readInt(); Data.NeedOverloadResolutionForDestructor = Record.readInt(); + Data.DefaultedCopyConstructorIsDeleted = Record.readInt(); Data.DefaultedMoveConstructorIsDeleted = Record.readInt(); Data.DefaultedMoveAssignmentIsDeleted = Record.readInt(); Data.DefaultedDestructorIsDeleted = Record.readInt(); @@ -1506,16 +1572,26 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.HasIrrelevantDestructor = Record.readInt(); Data.HasConstexprNonCopyMoveConstructor = Record.readInt(); Data.HasDefaultedDefaultConstructor = Record.readInt(); + Data.CanPassInRegisters = Record.readInt(); Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt(); Data.HasConstexprDefaultConstructor = Record.readInt(); Data.HasNonLiteralTypeFieldsOrBases = Record.readInt(); Data.ComputedVisibleConversions = Record.readInt(); Data.UserProvidedDefaultConstructor = Record.readInt(); Data.DeclaredSpecialMembers = Record.readInt(); - Data.ImplicitCopyConstructorHasConstParam = Record.readInt(); + Data.ImplicitCopyConstructorCanHaveConstParamForVBase = Record.readInt(); + Data.ImplicitCopyConstructorCanHaveConstParamForNonVBase = Record.readInt(); Data.ImplicitCopyAssignmentHasConstParam = Record.readInt(); Data.HasDeclaredCopyConstructorWithConstParam = Record.readInt(); Data.HasDeclaredCopyAssignmentWithConstParam = Record.readInt(); + Data.ODRHash = Record.readInt(); + Data.HasODRHash = true; + + if (Record.readInt()) { + Reader.BodySource[D] = Loc.F->Kind == ModuleKind::MK_MainFile + ? ExternalASTSource::EK_Never + : ExternalASTSource::EK_Always; + } Data.NumBases = Record.readInt(); if (Data.NumBases) @@ -1540,8 +1616,8 @@ void ASTDeclReader::ReadCXXDefinitionData( Lambda.NumExplicitCaptures = Record.readInt(); Lambda.ManglingNumber = Record.readInt(); Lambda.ContextDecl = ReadDeclID(); - Lambda.Captures - = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures); + Lambda.Captures = (Capture *)Reader.getContext().Allocate( + sizeof(Capture) * Lambda.NumCaptures); Capture *ToCapture = Lambda.Captures; Lambda.MethodTyInfo = GetTypeSourceInfo(); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { @@ -1624,9 +1700,11 @@ void ASTDeclReader::MergeDefinitionData( MATCH_FIELD(HasUninitializedFields) MATCH_FIELD(HasInheritedConstructor) MATCH_FIELD(HasInheritedAssignment) + MATCH_FIELD(NeedOverloadResolutionForCopyConstructor) MATCH_FIELD(NeedOverloadResolutionForMoveConstructor) MATCH_FIELD(NeedOverloadResolutionForMoveAssignment) MATCH_FIELD(NeedOverloadResolutionForDestructor) + MATCH_FIELD(DefaultedCopyConstructorIsDeleted) MATCH_FIELD(DefaultedMoveConstructorIsDeleted) MATCH_FIELD(DefaultedMoveAssignmentIsDeleted) MATCH_FIELD(DefaultedDestructorIsDeleted) @@ -1635,13 +1713,15 @@ void ASTDeclReader::MergeDefinitionData( MATCH_FIELD(HasIrrelevantDestructor) OR_FIELD(HasConstexprNonCopyMoveConstructor) OR_FIELD(HasDefaultedDefaultConstructor) + MATCH_FIELD(CanPassInRegisters) MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr) OR_FIELD(HasConstexprDefaultConstructor) MATCH_FIELD(HasNonLiteralTypeFieldsOrBases) // ComputedVisibleConversions is handled below. MATCH_FIELD(UserProvidedDefaultConstructor) OR_FIELD(DeclaredSpecialMembers) - MATCH_FIELD(ImplicitCopyConstructorHasConstParam) + MATCH_FIELD(ImplicitCopyConstructorCanHaveConstParamForVBase) + MATCH_FIELD(ImplicitCopyConstructorCanHaveConstParamForNonVBase) MATCH_FIELD(ImplicitCopyAssignmentHasConstParam) OR_FIELD(HasDeclaredCopyConstructorWithConstParam) OR_FIELD(HasDeclaredCopyAssignmentWithConstParam) @@ -1669,6 +1749,10 @@ void ASTDeclReader::MergeDefinitionData( // when they occur within the body of a function template specialization). } + if (D->getODRHash() != MergeDD.ODRHash) { + DetectedOdrViolation = true; + } + if (DetectedOdrViolation) Reader.PendingOdrMergeFailures[DD.Definition].push_back(MergeDD.Definition); } @@ -1686,7 +1770,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) { else DD = new (C) struct CXXRecordDecl::DefinitionData(D); - ReadCXXDefinitionData(*DD); + ReadCXXDefinitionData(*DD, D); // We might already have a definition for this record. This can happen either // because we're reading an update record, or because we've already done some @@ -1775,6 +1859,10 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { return Redecl; } +void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { + VisitFunctionDecl(D); +} + void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { VisitFunctionDecl(D); @@ -1804,8 +1892,6 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { } VisitCXXMethodDecl(D); - - D->IsExplicitSpecified = Record.readInt(); } void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { @@ -1821,7 +1907,6 @@ void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) { VisitCXXMethodDecl(D); - D->IsExplicitSpecified = Record.readInt(); } void ASTDeclReader::VisitImportDecl(ImportDecl *D) { @@ -1831,7 +1916,7 @@ void ASTDeclReader::VisitImportDecl(ImportDecl *D) { SourceLocation *StoredLocs = D->getTrailingObjects<SourceLocation>(); for (unsigned I = 0, N = Record.back(); I != N; ++I) StoredLocs[I] = ReadSourceLocation(); - (void)Record.readInt(); // The number of stored source locations. + Record.skipInts(1); // The number of stored source locations. } void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) { @@ -1873,6 +1958,7 @@ DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { DeclID PatternID = ReadDeclID(); NamedDecl *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID)); TemplateParameterList *TemplateParams = Record.readTemplateParameterList(); + // FIXME handle associated constraints D->init(TemplatedDecl, TemplateParams); return PatternID; @@ -1917,21 +2003,6 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { return Redecl; } -static DeclID *newDeclIDList(ASTContext &Context, DeclID *Old, - SmallVectorImpl<DeclID> &IDs) { - assert(!IDs.empty() && "no IDs to add to list"); - if (Old) { - IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); - std::sort(IDs.begin(), IDs.end()); - IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); - } - - auto *Result = new (Context) DeclID[1 + IDs.size()]; - *Result = IDs.size(); - std::copy(IDs.begin(), IDs.end(), Result + 1); - return Result; -} - void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); @@ -1940,19 +2011,14 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { // the specializations. SmallVector<serialization::DeclID, 32> SpecIDs; ReadDeclIDList(SpecIDs); - - if (!SpecIDs.empty()) { - auto *CommonPtr = D->getCommonPtr(); - CommonPtr->LazySpecializations = newDeclIDList( - Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); - } + ASTDeclReader::AddLazySpecializations(D, SpecIDs); } if (D->getTemplatedDecl()->TemplateOrInstantiation) { // We were loaded before our templated declaration was. We've not set up // its corresponding type yet (see VisitCXXRecordDeclImpl), so reconstruct // it now. - Reader.Context.getInjectedClassNameType( + Reader.getContext().getInjectedClassNameType( D->getTemplatedDecl(), D->getInjectedClassNameSpecialization()); } } @@ -1972,12 +2038,7 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { // the specializations. SmallVector<serialization::DeclID, 32> SpecIDs; ReadDeclIDList(SpecIDs); - - if (!SpecIDs.empty()) { - auto *CommonPtr = D->getCommonPtr(); - CommonPtr->LazySpecializations = newDeclIDList( - Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); - } + ASTDeclReader::AddLazySpecializations(D, SpecIDs); } } @@ -2083,12 +2144,7 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { // This FunctionTemplateDecl owns a CommonPtr; read it. SmallVector<serialization::DeclID, 32> SpecIDs; ReadDeclIDList(SpecIDs); - - if (!SpecIDs.empty()) { - auto *CommonPtr = D->getCommonPtr(); - CommonPtr->LazySpecializations = newDeclIDList( - Reader.getContext(), CommonPtr->LazySpecializations, SpecIDs); - } + ASTDeclReader::AddLazySpecializations(D, SpecIDs); } } @@ -2439,8 +2495,8 @@ void ASTDeclReader::mergeMergeable(Mergeable<T> *D) { if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) if (T *Existing = ExistingRes) - Reader.Context.setPrimaryMergedDecl(static_cast<T*>(D), - Existing->getCanonicalDecl()); + Reader.getContext().setPrimaryMergedDecl(static_cast<T *>(D), + Existing->getCanonicalDecl()); } void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { @@ -2471,12 +2527,12 @@ void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { //===----------------------------------------------------------------------===// /// \brief Reads attributes from the current stream position. -void ASTReader::ReadAttributes(ModuleFile &F, AttrVec &Attrs, - const RecordData &Record, unsigned &Idx) { - for (unsigned i = 0, e = Record[Idx++]; i != e; ++i) { +void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) { + for (unsigned i = 0, e = Record.readInt(); i != e; ++i) { Attr *New = nullptr; - attr::Kind Kind = (attr::Kind)Record[Idx++]; - SourceRange Range = ReadSourceRange(F, Record, Idx); + attr::Kind Kind = (attr::Kind)Record.readInt(); + SourceRange Range = Record.readSourceRange(); + ASTContext &Context = getContext(); #include "clang/Serialization/AttrPCHRead.inc" @@ -2531,7 +2587,11 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { Var->isThisDeclarationADefinition() == VarDecl::Definition; if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) return Func->doesThisDeclarationHaveABody() || HasBody; - + + if (auto *ES = D->getASTContext().getExternalSource()) + if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never) + return true; + return false; } @@ -2648,6 +2708,45 @@ static bool isSameTemplateParameterList(const TemplateParameterList *X, return true; } +/// Determine whether the attributes we can overload on are identical for A and +/// B. Will ignore any overloadable attrs represented in the type of A and B. +static bool hasSameOverloadableAttrs(const FunctionDecl *A, + const FunctionDecl *B) { + // Note that pass_object_size attributes are represented in the function's + // ExtParameterInfo, so we don't need to check them here. + + SmallVector<const EnableIfAttr *, 4> AEnableIfs; + // Since this is an equality check, we can ignore that enable_if attrs show up + // in reverse order. + for (const auto *EIA : A->specific_attrs<EnableIfAttr>()) + AEnableIfs.push_back(EIA); + + SmallVector<const EnableIfAttr *, 4> BEnableIfs; + for (const auto *EIA : B->specific_attrs<EnableIfAttr>()) + BEnableIfs.push_back(EIA); + + // Two very common cases: either we have 0 enable_if attrs, or we have an + // unequal number of enable_if attrs. + if (AEnableIfs.empty() && BEnableIfs.empty()) + return true; + + if (AEnableIfs.size() != BEnableIfs.size()) + return false; + + llvm::FoldingSetNodeID Cand1ID, Cand2ID; + for (unsigned I = 0, E = AEnableIfs.size(); I != E; ++I) { + Cand1ID.clear(); + Cand2ID.clear(); + + AEnableIfs[I]->getCond()->Profile(Cand1ID, A->getASTContext(), true); + BEnableIfs[I]->getCond()->Profile(Cand2ID, B->getASTContext(), true); + if (Cand1ID != Cand2ID) + return false; + } + + return true; +} + /// \brief Determine whether the two declarations refer to the same entity. static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!"); @@ -2703,8 +2802,24 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { CtorY->getInheritedConstructor().getConstructor())) return false; } - return (FuncX->getLinkageInternal() == FuncY->getLinkageInternal()) && - FuncX->getASTContext().hasSameType(FuncX->getType(), FuncY->getType()); + ASTContext &C = FuncX->getASTContext(); + if (!C.hasSameType(FuncX->getType(), FuncY->getType())) { + // We can get functions with different types on the redecl chain in C++17 + // if they have differing exception specifications and at least one of + // the excpetion specs is unresolved. + // FIXME: Do we need to check for C++14 deduced return types here too? + auto *XFPT = FuncX->getType()->getAs<FunctionProtoType>(); + auto *YFPT = FuncY->getType()->getAs<FunctionProtoType>(); + if (C.getLangOpts().CPlusPlus1z && XFPT && YFPT && + (isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) || + isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) && + C.hasSameFunctionTypeIgnoringExceptionSpec(FuncX->getType(), + FuncY->getType())) + return true; + return false; + } + return FuncX->getLinkageInternal() == FuncY->getLinkageInternal() && + hasSameOverloadableAttrs(FuncX, FuncY); } // Variables with the same type and linkage match. @@ -2816,7 +2931,7 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, // commit to DC being the canonical definition now, and will fix this when // we load the update record. if (!DD) { - DD = new (Reader.Context) struct CXXRecordDecl::DefinitionData(RD); + DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD); RD->IsCompleteDefinition = true; RD->DefinitionData = DD; RD->getCanonicalDecl()->DefinitionData = DD; @@ -3261,6 +3376,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { ASTDeclReader Reader(*this, Record, Loc, ID, DeclLoc); unsigned Code = DeclsCursor.ReadCode(); + ASTContext &Context = getContext(); Decl *D = nullptr; switch ((DeclCode)Record.readRecord(DeclsCursor, Code)) { case DECL_CONTEXT_LEXICAL: @@ -3323,6 +3439,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_CXX_RECORD: D = CXXRecordDecl::CreateDeserialized(Context, ID); break; + case DECL_CXX_DEDUCTION_GUIDE: + D = CXXDeductionGuideDecl::CreateDeserialized(Context, ID); + break; case DECL_CXX_METHOD: D = CXXMethodDecl::CreateDeserialized(Context, ID); break; @@ -3517,7 +3636,8 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { assert(Record.getIdx() == Record.size()); // Load any relevant update records. - PendingUpdateRecords.push_back(std::make_pair(ID, D)); + PendingUpdateRecords.push_back( + PendingUpdateRecord(ID, D, /*JustLoaded=*/true)); // Load the categories after recursive loading is finished. if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D)) @@ -3531,23 +3651,58 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { // AST consumer might need to know about, queue it. // We don't pass it to the consumer immediately because we may be in recursive // loading, and some declarations may still be initializing. - if (isConsumerInterestedIn(Context, D, Reader.hasPendingBody())) - InterestingDecls.push_back(D); + PotentiallyInterestingDecls.push_back( + InterestingDecl(D, Reader.hasPendingBody())); return D; } -void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { +void ASTReader::PassInterestingDeclsToConsumer() { + assert(Consumer); + + if (PassingDeclsToConsumer) + return; + + // Guard variable to avoid recursively redoing the process of passing + // decls to consumer. + SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer, + true); + + // Ensure that we've loaded all potentially-interesting declarations + // that need to be eagerly loaded. + for (auto ID : EagerlyDeserializedDecls) + GetDecl(ID); + EagerlyDeserializedDecls.clear(); + + while (!PotentiallyInterestingDecls.empty()) { + InterestingDecl D = PotentiallyInterestingDecls.front(); + PotentiallyInterestingDecls.pop_front(); + if (isConsumerInterestedIn(getContext(), D.getDecl(), D.hasPendingBody())) + PassInterestingDeclToConsumer(D.getDecl()); + } +} + +void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { // The declaration may have been modified by files later in the chain. // If this is the case, read the record containing the updates from each file // and pass it to ASTDeclReader to make the modifications. + serialization::GlobalDeclID ID = Record.ID; + Decl *D = Record.D; ProcessingUpdatesRAIIObj ProcessingUpdates(*this); DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); + + llvm::SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs; + if (UpdI != DeclUpdateOffsets.end()) { auto UpdateOffsets = std::move(UpdI->second); DeclUpdateOffsets.erase(UpdI); - bool WasInteresting = isConsumerInterestedIn(Context, D, false); + // Check if this decl was interesting to the consumer. If we just loaded + // the declaration, then we know it was interesting and we skip the call + // to isConsumerInterestedIn because it is unsafe to call in the + // current ASTReader state. + bool WasInteresting = + Record.JustLoaded || isConsumerInterestedIn(getContext(), D, false); for (auto &FileAndOffset : UpdateOffsets) { ModuleFile *F = FileAndOffset.first; uint64_t Offset = FileAndOffset.second; @@ -3562,17 +3717,29 @@ void ASTReader::loadDeclUpdateRecords(serialization::DeclID ID, Decl *D) { ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID, SourceLocation()); - Reader.UpdateDecl(D); + Reader.UpdateDecl(D, PendingLazySpecializationIDs); // We might have made this declaration interesting. If so, remember that // we need to hand it off to the consumer. if (!WasInteresting && - isConsumerInterestedIn(Context, D, Reader.hasPendingBody())) { - InterestingDecls.push_back(D); + isConsumerInterestedIn(getContext(), D, Reader.hasPendingBody())) { + PotentiallyInterestingDecls.push_back( + InterestingDecl(D, Reader.hasPendingBody())); WasInteresting = true; } } } + // Add the lazy specializations to the template. + assert((PendingLazySpecializationIDs.empty() || isa<ClassTemplateDecl>(D) || + isa<FunctionTemplateDecl>(D) || isa<VarTemplateDecl>(D)) && + "Must not have pending specializations"); + if (auto *CTD = dyn_cast<ClassTemplateDecl>(D)) + ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs); + else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) + ASTDeclReader::AddLazySpecializations(FTD, PendingLazySpecializationIDs); + else if (auto *VTD = dyn_cast<VarTemplateDecl>(D)) + ASTDeclReader::AddLazySpecializations(VTD, PendingLazySpecializationIDs); + PendingLazySpecializationIDs.clear(); // Load the pending visible updates for this decl context, if it has any. auto I = PendingVisibleUpdates.find(ID); @@ -3769,7 +3936,8 @@ static void forAllLaterRedecls(DeclT *D, Fn F) { } } -void ASTDeclReader::UpdateDecl(Decl *D) { +void ASTDeclReader::UpdateDecl(Decl *D, + llvm::SmallVectorImpl<serialization::DeclID> &PendingLazySpecializationIDs) { while (Record.getIdx() < Record.size()) { switch ((DeclUpdateKind)Record.readInt()) { case UPD_CXX_ADDED_IMPLICIT_MEMBER: { @@ -3785,8 +3953,8 @@ void ASTDeclReader::UpdateDecl(Decl *D) { } case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION: - // It will be added to the template's specializations set when loaded. - (void)Record.readDecl(); + // It will be added to the template's lazy specialization set. + PendingLazySpecializationIDs.push_back(ReadDeclID()); break; case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: { @@ -3804,10 +3972,21 @@ void ASTDeclReader::UpdateDecl(Decl *D) { break; } - case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: - cast<VarDecl>(D)->getMemberSpecializationInfo()->setPointOfInstantiation( + case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: { + VarDecl *VD = cast<VarDecl>(D); + VD->getMemberSpecializationInfo()->setPointOfInstantiation( ReadSourceLocation()); + uint64_t Val = Record.readInt(); + if (Val && !VD->getInit()) { + VD->setInit(Record.readExpr()); + if (Val > 1) { // IsInitKnownICE = 1, IsInitNotICE = 2, IsInitICE = 3 + EvaluatedStmt *Eval = VD->ensureEvaluatedStmt(); + Eval->CheckedICE = true; + Eval->IsICE = Val == 3; + } + } break; + } case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: { auto Param = cast<ParmVarDecl>(D); @@ -3858,14 +4037,7 @@ void ASTDeclReader::UpdateDecl(Decl *D) { }); } FD->setInnerLocStart(ReadSourceLocation()); - if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { - CD->NumCtorInitializers = Record.readInt(); - if (CD->NumCtorInitializers) - CD->CtorInitializers = ReadGlobalOffset(); - } - // Store the offset of the body so we can lazily load it later. - Reader.PendingBodies[FD] = GetCurrentCursorOffset(); - HasPendingBody = true; + ReadFunctionDefinition(FD); assert(Record.getIdx() == Record.size() && "lazy body must be last"); break; } @@ -3951,7 +4123,7 @@ void ASTDeclReader::UpdateDecl(Decl *D) { // FIXME: If the exception specification is already present, check that it // matches. if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) { - FD->setType(Reader.Context.getFunctionType( + FD->setType(Reader.getContext().getFunctionType( FPT->getReturnType(), FPT->getParamTypes(), FPT->getExtProtoInfo().withExceptionSpec(ESI))); @@ -3969,28 +4141,31 @@ void ASTDeclReader::UpdateDecl(Decl *D) { for (auto *Redecl : merged_redecls(D)) { // FIXME: If the return type is already deduced, check that it matches. FunctionDecl *FD = cast<FunctionDecl>(Redecl); - Reader.Context.adjustDeducedFunctionResultType(FD, DeducedResultType); + Reader.getContext().adjustDeducedFunctionResultType(FD, + DeducedResultType); } break; } case UPD_DECL_MARKED_USED: { // Maintain AST consistency: any later redeclarations are used too. - D->markUsed(Reader.Context); + D->markUsed(Reader.getContext()); break; } case UPD_MANGLING_NUMBER: - Reader.Context.setManglingNumber(cast<NamedDecl>(D), Record.readInt()); + Reader.getContext().setManglingNumber(cast<NamedDecl>(D), + Record.readInt()); break; case UPD_STATIC_LOCAL_NUMBER: - Reader.Context.setStaticLocalNumber(cast<VarDecl>(D), Record.readInt()); + Reader.getContext().setStaticLocalNumber(cast<VarDecl>(D), + Record.readInt()); break; case UPD_DECL_MARKED_OPENMP_THREADPRIVATE: - D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit( - Reader.Context, ReadSourceRange())); + D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(Reader.getContext(), + ReadSourceRange())); break; case UPD_DECL_EXPORTED: { @@ -4010,7 +4185,7 @@ void ASTDeclReader::UpdateDecl(Decl *D) { Reader.HiddenNamesMap[Owner].push_back(Exported); } else { // The declaration is now visible. - Exported->Hidden = false; + Exported->setVisibleDespiteOwningModule(); } break; } |