Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

The ICE in the linked PR is caused because name lookup finds duplicate
copies of the deduction guides, causing a checking assert to fail.

This is ultimately because we're exporting an imported guide; when name
lookup processes 'dguide-5_b.H' it goes via the 'tt_entity' path and
just returns the entity from 'dguide-5_a.H'.  Because this doesn't ever
go through 'key_mergeable' we never set 'BINDING_VECTOR_GLOBAL_DUPS_P'
and so deduping is not engaged, allowing duplicate results.

Currently I believe this to be a perculiarity of the ANY_REACHABLE
handling for deduction guides; in no other case that I can find do we
emit bindings purely to imported entities.  As such, this patch fixes
this problem from that end, by ensuring that we simply do not emit any
imported deduction guides.  This avoids the ICE because no duplicates
need deduping to start with, and should otherwise have no functional
change because lookup of deduction guides will look at all reachable
modules (exported or not) regardless.

Since we're now deliberately not emitting imported deduction guides we
can use LOOK_want::NORMAL instead of LOOK_want::ANY_REACHABLE, since the
extra work to find as-yet undiscovered deduction guides in transitive
importers is not necessary here.

        PR c++/117397

gcc/cp/ChangeLog:

        * module.cc (depset::hash::add_deduction_guides): Don't emit
        imported deduction guides.

gcc/testsuite/ChangeLog:

        * g++.dg/modules/dguide-5_a.H: New test.
        * g++.dg/modules/dguide-5_b.H: New test.
        * g++.dg/modules/dguide-5_c.H: New test.

Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>
---
 gcc/cp/module.cc                          | 30 +++++++++++++++--------
 gcc/testsuite/g++.dg/modules/dguide-5_a.H |  6 +++++
 gcc/testsuite/g++.dg/modules/dguide-5_b.H |  6 +++++
 gcc/testsuite/g++.dg/modules/dguide-5_c.H |  7 ++++++
 4 files changed, 39 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/dguide-5_a.H
 create mode 100644 gcc/testsuite/g++.dg/modules/dguide-5_b.H
 create mode 100644 gcc/testsuite/g++.dg/modules/dguide-5_c.H

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 51990f36284..c4df18b9ca9 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -14341,22 +14341,32 @@ depset::hash::add_deduction_guides (tree decl)
   if (find_binding (ns, name))
     return;
 
-  tree guides = lookup_qualified_name (ns, name, LOOK_want::ANY_REACHABLE,
+  tree guides = lookup_qualified_name (ns, name, LOOK_want::NORMAL,
                                       /*complain=*/false);
   if (guides == error_mark_node)
     return;
 
-  /* We have bindings to add.  */
-  depset *binding = make_binding (ns, name);
-  add_namespace_context (binding, ns);
+  depset *binding = nullptr;
+  for (tree t : lkp_range (guides))
+    {
+      /* We don't want to export imported deduction guides, since searches will
+        look there anyway.  */
+      if (DECL_LANG_SPECIFIC (STRIP_TEMPLATE (t))
+         && DECL_MODULE_IMPORT_P (STRIP_TEMPLATE (t)))
+       continue;
 
-  depset **slot = binding_slot (ns, name, /*insert=*/true);
-  *slot = binding;
+      if (!binding)
+       {
+         /* We have bindings to add.  */
+         binding = make_binding (ns, name);
+         add_namespace_context (binding, ns);
 
-  for (lkp_iterator it (guides); it; ++it)
-    {
-      gcc_checking_assert (!TREE_VISITED (*it));
-      depset *dep = make_dependency (*it, EK_FOR_BINDING);
+         depset **slot = binding_slot (ns, name, /*insert=*/true);
+         *slot = binding;
+       }
+
+      gcc_checking_assert (!TREE_VISITED (t));
+      depset *dep = make_dependency (t, EK_FOR_BINDING);
       binding->deps.safe_push (dep);
       dep->deps.safe_push (binding);
     }
diff --git a/gcc/testsuite/g++.dg/modules/dguide-5_a.H 
b/gcc/testsuite/g++.dg/modules/dguide-5_a.H
new file mode 100644
index 00000000000..42421059c7f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dguide-5_a.H
@@ -0,0 +1,6 @@
+// PR c++/117397
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template <typename T> struct S;
+template <typename T> S(T) -> S<T>;
diff --git a/gcc/testsuite/g++.dg/modules/dguide-5_b.H 
b/gcc/testsuite/g++.dg/modules/dguide-5_b.H
new file mode 100644
index 00000000000..d31f24d54de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dguide-5_b.H
@@ -0,0 +1,6 @@
+// PR c++/117397
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+import "dguide-5_a.H";
+template <typename T> struct S;
diff --git a/gcc/testsuite/g++.dg/modules/dguide-5_c.H 
b/gcc/testsuite/g++.dg/modules/dguide-5_c.H
new file mode 100644
index 00000000000..a9bf2dd0583
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/dguide-5_c.H
@@ -0,0 +1,7 @@
+// PR c++/117397
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+template <typename T> struct S;
+import "dguide-5_b.H";
+S<int> foo();
-- 
2.47.0

Reply via email to