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 <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 } }