diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ba9e848c177..7ae5b876735 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7420,6 +7420,7 @@ extern unsigned get_importing_module (tree, bool = false) ATTRIBUTE_PURE; /* Where current instance of the decl got declared/defined/instantiated. */ extern void set_instantiating_module (tree); extern void set_defining_module (tree); +extern void set_defining_module_for_partial_spec (tree); extern void maybe_key_decl (tree ctx, tree decl); extern void propagate_defining_module (tree decl, tree orig); extern void remove_defining_module (tree decl); diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 520dd710549..3ca963cb3e9 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -8416,6 +8416,11 @@ trees_in::decl_value () add_mergeable_specialization (!is_type, &spec, decl, spec_flags); } + /* When making a CMI from a partition we're going to need to walk partial + specializations again, so make sure they're tracked. */ + if (state->is_partition () && (spec_flags & 2)) + set_defining_module_for_partial_spec (inner); + if (NAMESPACE_SCOPE_P (decl) && (mk == MK_named || mk == MK_unique || mk == MK_enum || mk == MK_friend_spec) @@ -19246,13 +19251,22 @@ set_defining_module (tree decl) vec_safe_push (class_members, decl); } } - else if (DECL_IMPLICIT_TYPEDEF_P (decl) - && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl))) - /* This is a partial or explicit specialization. */ - vec_safe_push (partial_specializations, decl); } } +/* Also remember DECL if it's a newly declared class template partial + specialization, because these are not necessarily added to the + instantiation tables. */ + +void +set_defining_module_for_partial_spec (tree decl) +{ + if (module_p () + && DECL_IMPLICIT_TYPEDEF_P (decl) + && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl))) + vec_safe_push (partial_specializations, decl); +} + void set_originating_module (tree decl, bool friend_p ATTRIBUTE_UNUSED) { diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index a95ce6eb3da..dfce1b3c359 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -5456,6 +5456,8 @@ process_partial_specialization (tree decl) gcc_checking_assert (!TI_PARTIAL_INFO (tinfo)); TI_PARTIAL_INFO (tinfo) = build_template_info (tmpl, NULL_TREE); + set_defining_module_for_partial_spec (decl); + for (inst = DECL_TEMPLATE_INSTANTIATIONS (maintmpl); inst; inst = TREE_CHAIN (inst)) { diff --git a/gcc/testsuite/g++.dg/modules/partial-4_a.C b/gcc/testsuite/g++.dg/modules/partial-4_a.C new file mode 100644 index 00000000000..e74bb0ad866 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-4_a.C @@ -0,0 +1,8 @@ +// PR c++/114947 +// { dg-additional-options "-fmodules-ts -std=c++20" } +// { dg-module-cmi M:part } +module M:part; + +template struct R {}; +template requires false struct R {}; +template requires true struct R; diff --git a/gcc/testsuite/g++.dg/modules/partial-4_b.C b/gcc/testsuite/g++.dg/modules/partial-4_b.C new file mode 100644 index 00000000000..1c645671a55 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-4_b.C @@ -0,0 +1,5 @@ +// PR c++/114947 +// { dg-additional-options "-fmodules-ts -std=c++20" } +// { dg-module-cmi M } +export module M; +import :part;