Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 --
The change in r14-8408 to also emit partial specializations in the global module fragment caused the regression in the linked PR; this patch fixes this by restricting emitted GM partial specializations to those that are actually used. PR c++/114630 gcc/cp/ChangeLog: * module.cc (depset::hash::add_partial_entities): Mark GM specializations as unreached. (depset::hash::find_dependencies): Also reach entities in the DECL_TEMPLATE_SPECIALIZATIONS list. gcc/testsuite/ChangeLog: * g++.dg/modules/partial-3.C: New test. Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> --- gcc/cp/module.cc | 75 +++++++++++++++--------- gcc/testsuite/g++.dg/modules/partial-3.C | 20 +++++++ 2 files changed, 66 insertions(+), 29 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/partial-3.C diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index fac0301d80e..02b0ab3d687 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -13304,14 +13304,22 @@ depset::hash::add_partial_entities (vec<tree, va_gc> *partial_classes) depset *dep = make_dependency (inner, depset::EK_DECL); if (dep->get_entity_kind () == depset::EK_REDIRECT) - /* We should have recorded the template as a partial - specialization. */ - gcc_checking_assert (dep->deps[0]->get_entity_kind () - == depset::EK_PARTIAL); + { + dep = dep->deps[0]; + /* We should have recorded the template as a partial + specialization. */ + gcc_checking_assert (dep->get_entity_kind () + == depset::EK_PARTIAL); + } else /* It was an explicit specialization, not a partial one. */ gcc_checking_assert (dep->get_entity_kind () == depset::EK_SPECIALIZATION); + + /* Only emit GM entities if reached. */ + if (!DECL_LANG_SPECIFIC (inner) + || !DECL_MODULE_PURVIEW_P (inner)) + dep->set_flag_bit<DB_UNREACHED_BIT> (); } } @@ -13632,31 +13640,40 @@ depset::hash::find_dependencies (module_state *module) if (!walker.is_key_order () && TREE_CODE (decl) == TEMPLATE_DECL && !DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl)) - /* Mark all the explicit & partial specializations as - reachable. */ - for (tree cons = DECL_TEMPLATE_INSTANTIATIONS (decl); - cons; cons = TREE_CHAIN (cons)) - { - tree spec = TREE_VALUE (cons); - if (TYPE_P (spec)) - spec = TYPE_NAME (spec); - int use_tpl; - node_template_info (spec, use_tpl); - if (use_tpl & 2) - { - depset *spec_dep = find_dependency (spec); - if (spec_dep->get_entity_kind () == EK_REDIRECT) - spec_dep = spec_dep->deps[0]; - if (spec_dep->is_unreached ()) - { - reached_unreached = true; - spec_dep->clear_flag_bit<DB_UNREACHED_BIT> (); - dump (dumper::DEPEND) - && dump ("Reaching unreached specialization" - " %C:%N", TREE_CODE (spec), spec); - } - } - } + { + /* Mark all the explicit & partial specializations as + reachable. We search both specialization lists as some + constrained partial specializations for class types are + only found in DECL_TEMPLATE_SPECIALIZATIONS. */ + auto mark_reached = [this](tree spec) + { + if (TYPE_P (spec)) + spec = TYPE_NAME (spec); + int use_tpl; + node_template_info (spec, use_tpl); + if (use_tpl & 2) + { + depset *spec_dep = find_dependency (spec); + if (spec_dep->get_entity_kind () == EK_REDIRECT) + spec_dep = spec_dep->deps[0]; + if (spec_dep->is_unreached ()) + { + reached_unreached = true; + spec_dep->clear_flag_bit<DB_UNREACHED_BIT> (); + dump (dumper::DEPEND) + && dump ("Reaching unreached specialization" + " %C:%N", TREE_CODE (spec), spec); + } + } + }; + + for (tree cons = DECL_TEMPLATE_INSTANTIATIONS (decl); + cons; cons = TREE_CHAIN (cons)) + mark_reached (TREE_VALUE (cons)); + for (tree cons = DECL_TEMPLATE_SPECIALIZATIONS (decl); + cons; cons = TREE_CHAIN (cons)) + mark_reached (TREE_VALUE (cons)); + } dump.outdent (); current = NULL; diff --git a/gcc/testsuite/g++.dg/modules/partial-3.C b/gcc/testsuite/g++.dg/modules/partial-3.C new file mode 100644 index 00000000000..0d498dad1bd --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-3.C @@ -0,0 +1,20 @@ +// PR c++/114630 +// { dg-additional-options "-fmodules-ts -std=c++20 -Wno-global-module -fdump-lang-module" } +// { dg-module-cmi M } + +module; + +template <typename T> struct S {}; + +template <typename T> struct S<T*> {}; +template <typename T> requires (sizeof(T) == 4) struct S<T*> {}; + +template <typename T> int V = 0; + +template <typename T> int V<T*> = 1; +template <typename T> requires (sizeof(T) == 4) int V<T*> = 2; + +export module M; + +// The whole GMF should be discarded here +// { dg-final { scan-lang-dump "Wrote 0 clusters" module } } -- 2.43.2