Author: Michael Park Date: 2025-02-03T11:22:02-08:00 New Revision: a9e249f64e800fbb20a3b26c0cfb68c1a1aee5e1
URL: https://github.com/llvm/llvm-project/commit/a9e249f64e800fbb20a3b26c0cfb68c1a1aee5e1 DIFF: https://github.com/llvm/llvm-project/commit/a9e249f64e800fbb20a3b26c0cfb68c1a1aee5e1.diff LOG: [C++20][Modules][Serialization] Delay marking pending incomplete decl chains until the end of `finishPendingActions`. (#121245) The call to `hasBody` inside `finishPendingActions` that bumps the `PendingIncompleteDeclChains` size from `0` to `1`, and also sets the `LazyVal->LastGeneration` to `6` which matches the `LazyVal->ExternalSource->getGeneration()` value of `6`. Later, the iterations over `redecls()` (which calls `getNextRedeclaration`) is expected to trigger the reload, but it **does not** since the generation numbers match. The proposed solution is to perform the marking of incomplete decl chains at the end of `finishPendingActions`. This way, **all** of the incomplete decls are marked incomplete as a post-condition of `finishPendingActions`. It's also safe to delay this operation since any operation being done within `finishPendingActions` has `NumCurrentElementsDeserializing == 1`, which means that any calls to `CompleteDeclChain` would simply add to the `PendingIncompleteDeclChains` without doing anything anyway. Added: clang/test/Modules/pr121245.cpp Modified: clang/lib/Serialization/ASTReader.cpp Removed: ################################################################################ diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index f524251c48ddd7..24acd6e297e712 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -10186,12 +10186,12 @@ void ASTReader::visitTopLevelModuleMaps( } void ASTReader::finishPendingActions() { - while ( - !PendingIdentifierInfos.empty() || !PendingDeducedFunctionTypes.empty() || - !PendingDeducedVarTypes.empty() || !PendingIncompleteDeclChains.empty() || - !PendingDeclChains.empty() || !PendingMacroIDs.empty() || - !PendingDeclContextInfos.empty() || !PendingUpdateRecords.empty() || - !PendingObjCExtensionIvarRedeclarations.empty()) { + while (!PendingIdentifierInfos.empty() || + !PendingDeducedFunctionTypes.empty() || + !PendingDeducedVarTypes.empty() || !PendingDeclChains.empty() || + !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() || + !PendingUpdateRecords.empty() || + !PendingObjCExtensionIvarRedeclarations.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. using TopLevelDeclsMap = @@ -10239,13 +10239,6 @@ void ASTReader::finishPendingActions() { } PendingDeducedVarTypes.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) { - markIncompleteDeclChain(PendingIncompleteDeclChains[I]); - } - PendingIncompleteDeclChains.clear(); - // Load pending declaration chains. for (unsigned I = 0; I != PendingDeclChains.size(); ++I) loadPendingDeclChain(PendingDeclChains[I].first, @@ -10483,6 +10476,12 @@ void ASTReader::finishPendingActions() { for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); PendingMergedDefinitionsToDeduplicate.clear(); + + // For each decl chain that we wanted to complete while deserializing, mark + // it as "still needs to be completed". + for (Decl *D : PendingIncompleteDeclChains) + markIncompleteDeclChain(D); + PendingIncompleteDeclChains.clear(); } void ASTReader::diagnoseOdrViolations() { diff --git a/clang/test/Modules/pr121245.cpp b/clang/test/Modules/pr121245.cpp new file mode 100644 index 00000000000000..0e276ad0e435d1 --- /dev/null +++ b/clang/test/Modules/pr121245.cpp @@ -0,0 +1,93 @@ +// If this test fails, it should be investigated under Debug builds. +// Before the PR, this test was encountering an `llvm_unreachable()`. + +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// RUN: cd %t + +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header %t/hu-01.h \ +// RUN: -fcxx-exceptions -o %t/hu-01.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header %t/hu-02.h \ +// RUN: -Wno-experimental-header-units -fcxx-exceptions \ +// RUN: -fmodule-file=%t/hu-01.pcm -o %t/hu-02.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header %t/hu-03.h \ +// RUN: -Wno-experimental-header-units -fcxx-exceptions \ +// RUN: -fmodule-file=%t/hu-01.pcm -o %t/hu-03.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header %t/hu-04.h \ +// RUN: -Wno-experimental-header-units -fcxx-exceptions \ +// RUN: -fmodule-file=%t/hu-01.pcm -o %t/hu-04.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header %t/hu-05.h \ +// RUN: -Wno-experimental-header-units -fcxx-exceptions \ +// RUN: -fmodule-file=%t/hu-03.pcm -fmodule-file=%t/hu-04.pcm \ +// RUN: -fmodule-file=%t/hu-01.pcm -o %t/hu-05.pcm + +// RUN: %clang_cc1 -std=c++20 -emit-obj %t/main.cpp \ +// RUN: -Wno-experimental-header-units -fcxx-exceptions \ +// RUN: -fmodule-file=%t/hu-02.pcm -fmodule-file=%t/hu-05.pcm \ +// RUN: -fmodule-file=%t/hu-04.pcm -fmodule-file=%t/hu-03.pcm \ +// RUN: -fmodule-file=%t/hu-01.pcm + +//--- hu-01.h +template <typename T> +struct A { + A() {} + ~A() {} +}; + +template <typename T> +struct EBO : T { + EBO() = default; +}; + +template <typename T> +struct HT : EBO<A<T>> {}; + +//--- hu-02.h +import "hu-01.h"; + +inline void f() { + HT<int>(); +} + +//--- hu-03.h +import "hu-01.h"; + +struct C { + C(); + + HT<long> _; +}; + +//--- hu-04.h +import "hu-01.h"; + +void g(HT<long> = {}); + +//--- hu-05.h +import "hu-03.h"; +import "hu-04.h"; +import "hu-01.h"; + +struct B { + virtual ~B() = default; + + virtual void f() { + HT<long>(); + } +}; + +//--- main.cpp +import "hu-02.h"; +import "hu-05.h"; +import "hu-03.h"; + +int main() { + f(); + C(); + B(); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits