Message ID | 6632129e.050a0220.c5fe4.327c@mx.google.com |
---|---|
State | New |
Headers | show |
Series | c++/modules: Fix missed GMF discarding | expand |
On 5/1/24 02:59, Nathaniel Shead wrote: > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? OK. > -- >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 <nathanieloshead@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 } }
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 } }
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 <nathanieloshead@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