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

Reply via email to