diff options
Diffstat (limited to 'clang/lib/Serialization')
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 42 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 36 |
2 files changed, 58 insertions, 20 deletions
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 723839ff62b..8a02ea93f40 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -9254,7 +9254,7 @@ std::string ASTReader::getOwningModuleNameForDiagnostic(const Decl *D) { } void ASTReader::finishPendingActions() { - while (!PendingIdentifierInfos.empty() || + while (!PendingIdentifierInfos.empty() || !PendingFunctionTypes.empty() || !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() || !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() || !PendingUpdateRecords.empty()) { @@ -9273,6 +9273,21 @@ void ASTReader::finishPendingActions() { SetGloballyVisibleDecls(II, DeclIDs, &TopLevelDecls[II]); } + // Load each function type that we deferred loading because it was a + // deduced type that might refer to a local type declared within itself. + for (unsigned I = 0; I != PendingFunctionTypes.size(); ++I) { + auto *FD = PendingFunctionTypes[I].first; + FD->setType(GetType(PendingFunctionTypes[I].second)); + + // If we gave a function a deduced return type, remember that we need to + // propagate that along the redeclaration chain. + auto *DT = FD->getReturnType()->getContainedDeducedType(); + if (DT && DT->isDeduced()) + PendingDeducedTypeUpdates.insert( + {FD->getCanonicalDecl(), FD->getReturnType()}); + } + PendingFunctionTypes.clear(); + // For each decl chain that we wanted to complete while deserializing, mark // it as "still needs to be completed". for (unsigned I = 0; I != PendingIncompleteDeclChains.size(); ++I) { @@ -9282,7 +9297,8 @@ void ASTReader::finishPendingActions() { // Load pending declaration chains. for (unsigned I = 0; I != PendingDeclChains.size(); ++I) - loadPendingDeclChain(PendingDeclChains[I].first, PendingDeclChains[I].second); + loadPendingDeclChain(PendingDeclChains[I].first, + PendingDeclChains[I].second); PendingDeclChains.clear(); // Make the most recent of the top-level declarations visible. @@ -11531,11 +11547,16 @@ void ASTReader::FinishedDeserializing() { --NumCurrentElementsDeserializing; if (NumCurrentElementsDeserializing == 0) { - // Propagate exception specification updates along redeclaration chains. - while (!PendingExceptionSpecUpdates.empty()) { - auto Updates = std::move(PendingExceptionSpecUpdates); + // Propagate exception specification and deduced type updates along + // redeclaration chains. + // + // We do this now rather than in finishPendingActions because we want to + // be able to walk the complete redeclaration chains of the updated decls. + while (!PendingExceptionSpecUpdates.empty() || + !PendingDeducedTypeUpdates.empty()) { + auto ESUpdates = std::move(PendingExceptionSpecUpdates); PendingExceptionSpecUpdates.clear(); - for (auto Update : Updates) { + for (auto Update : ESUpdates) { ProcessingUpdatesRAIIObj ProcessingUpdates(*this); auto *FPT = Update.second->getType()->castAs<FunctionProtoType>(); auto ESI = FPT->getExtProtoInfo().ExceptionSpec; @@ -11544,6 +11565,15 @@ void ASTReader::FinishedDeserializing() { for (auto *Redecl : Update.second->redecls()) getContext().adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI); } + + auto DTUpdates = std::move(PendingDeducedTypeUpdates); + PendingDeducedTypeUpdates.clear(); + for (auto Update : DTUpdates) { + ProcessingUpdatesRAIIObj ProcessingUpdates(*this); + // FIXME: If the return type is already deduced, check that it matches. + getContext().adjustDeducedFunctionResultType(Update.first, + Update.second); + } } if (ReadTimer) diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index d17ec8e0461..613579d9079 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -541,9 +541,6 @@ void ASTDeclReader::Visit(Decl *D) { // if we have a fully initialized TypeDecl, we can safely read its type now. ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull(); } else if (auto *FD = dyn_cast<FunctionDecl>(D)) { - if (DeferredTypeID) - FD->setType(Reader.GetType(DeferredTypeID)); - // FunctionDecl's body was written last after all other Stmts/Exprs. // We only read it if FD doesn't already have a body (e.g., from another // module). @@ -844,10 +841,11 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { // We'll set up the real type in Visit, once we've finished loading the // function. FD->setType(FD->getTypeSourceInfo()->getType()); + Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID}); } else { FD->setType(Reader.GetType(DeferredTypeID)); - DeferredTypeID = 0; } + DeferredTypeID = 0; ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName()); FD->IdentifierNamespace = Record.readInt(); @@ -3370,6 +3368,11 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, } } +static bool isUndeducedReturnType(QualType T) { + auto *DT = T->getContainedDeducedType(); + return DT && !DT->isDeduced(); +} + template<> void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, Redeclarable<FunctionDecl> *D, @@ -3401,17 +3404,26 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, FD->setImplicitlyInline(true); } - // If we need to propagate an exception specification along the redecl - // chain, make a note of that so that we can do so later. auto *FPT = FD->getType()->getAs<FunctionProtoType>(); auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>(); if (FPT && PrevFPT) { + // If we need to propagate an exception specification along the redecl + // chain, make a note of that so that we can do so later. bool IsUnresolved = isUnresolvedExceptionSpec(FPT->getExceptionSpecType()); bool WasUnresolved = isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType()); if (IsUnresolved != WasUnresolved) Reader.PendingExceptionSpecUpdates.insert( - std::make_pair(Canon, IsUnresolved ? PrevFD : FD)); + {Canon, IsUnresolved ? PrevFD : FD}); + + // If we need to propagate a deduced return type along the redecl chain, + // make a note of that so that we can do it later. + bool IsUndeduced = isUndeducedReturnType(FPT->getReturnType()); + bool WasUndeduced = isUndeducedReturnType(PrevFPT->getReturnType()); + if (IsUndeduced != WasUndeduced) + Reader.PendingDeducedTypeUpdates.insert( + {cast<FunctionDecl>(Canon), + (IsUndeduced ? PrevFPT : FPT)->getReturnType()}); } } @@ -4328,14 +4340,10 @@ void ASTDeclReader::UpdateDecl(Decl *D, } case UPD_CXX_DEDUCED_RETURN_TYPE: { - // FIXME: Also do this when merging redecls. + auto *FD = cast<FunctionDecl>(D); QualType DeducedResultType = Record.readType(); - for (auto *Redecl : merged_redecls(D)) { - // FIXME: If the return type is already deduced, check that it matches. - auto *FD = cast<FunctionDecl>(Redecl); - Reader.getContext().adjustDeducedFunctionResultType(FD, - DeducedResultType); - } + Reader.PendingDeducedTypeUpdates.insert( + {FD->getCanonicalDecl(), DeducedResultType}); break; } |