On Mon, Jan 13, 2025 at 07:00:18PM -0500, Jason Merrill wrote:
> On 1/12/25 7:03 AM, Nathaniel Shead wrote:
> > On Sun, Jan 12, 2025 at 04:14:41AM +1100, Nathaniel Shead wrote:
> > > 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;
> > 
> > Actually on further thought, this is not correct; this will prevent us
> > from exporting declarations inherited from a partition.  Here's an
> > updated version of the patch that will handle this properly (using
> > depset::is_import which handles this case correctly) and with a bonus
> > assertion re: bindings of imported decls to help ensure we don't run
> > into similar errors in the future.
> > 
> > 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.
> 
> OK.
> 
> Do we still need any_reachable in check_module_override?
> 

Thanks.  And yes, otherwise the check for an ambiguating declaration of

  Attached(int) -> Attached<double>;

in dguide-4_c.C doesn't error; we still need to find all reachable
imports for the error here.

> >     PR c++/117397
> > 
> > gcc/cp/ChangeLog:
> > 
> >     * module.cc (depset::hash::add_deduction_guides): Don't emit
> >     imported deduction guides.
> >     (depset::hash::finalize_dependencies): Add check for any
> >     bindings referring to imported entities.
> > 
> > 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.
> >     * g++.dg/modules/dguide-6.h: New test.
> >     * g++.dg/modules/dguide-6_a.C: New test.
> >     * g++.dg/modules/dguide-6_b.C: New test.
> >     * g++.dg/modules/dguide-6_c.C: New test.
> > 
> > Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>
> > ---
> >   gcc/cp/module.cc                          | 35 ++++++++++++++++-------
> >   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 +++++
> >   gcc/testsuite/g++.dg/modules/dguide-6.h   |  4 +++
> >   gcc/testsuite/g++.dg/modules/dguide-6_a.C |  7 +++++
> >   gcc/testsuite/g++.dg/modules/dguide-6_b.C |  8 ++++++
> >   gcc/testsuite/g++.dg/modules/dguide-6_c.C | 12 ++++++++
> >   8 files changed, 75 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
> >   create mode 100644 gcc/testsuite/g++.dg/modules/dguide-6.h
> >   create mode 100644 gcc/testsuite/g++.dg/modules/dguide-6_a.C
> >   create mode 100644 gcc/testsuite/g++.dg/modules/dguide-6_b.C
> >   create mode 100644 gcc/testsuite/g++.dg/modules/dguide-6_c.C
> > 
> > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> > index 51990f36284..61116fe7669 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))
> > +    {
> > +      gcc_checking_assert (!TREE_VISITED (t));
> > +      depset *dep = make_dependency (t, EK_FOR_BINDING);
> > -  depset **slot = binding_slot (ns, name, /*insert=*/true);
> > -  *slot = binding;
> > +      /* We don't want to create bindings for imported deduction guides, as
> > +    this would potentially cause name lookup to return duplicates.  */
> > +      if (dep->is_import ())
> > +   continue;
> > +
> > +      if (!binding)
> > +   {
> > +     /* We have bindings to add.  */
> > +     binding = make_binding (ns, name);
> > +     add_namespace_context (binding, ns);
> > +
> > +     depset **slot = binding_slot (ns, name, /*insert=*/true);
> > +     *slot = binding;
> > +   }
> > -  for (lkp_iterator it (guides); it; ++it)
> > -    {
> > -      gcc_checking_assert (!TREE_VISITED (*it));
> > -      depset *dep = make_dependency (*it, EK_FOR_BINDING);
> >         binding->deps.safe_push (dep);
> >         dep->deps.safe_push (binding);
> >       }
> > @@ -14592,6 +14602,11 @@ depset::hash::finalize_dependencies ()
> >       if (dep->deps.length () > 2)
> >         gcc_qsort (&dep->deps[1], dep->deps.length () - 1,
> >                    sizeof (dep->deps[1]), binding_cmp);
> > +
> > +     /* Bindings shouldn't refer to imported entities.  */
> > +     if (CHECKING_P)
> > +       for (depset *entity : dep->deps)
> > +         gcc_checking_assert (!entity->is_import ());
> >     }
> >         else if (dep->is_exposure () && !dep->is_tu_local ())
> >     {
> > 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();
> > diff --git a/gcc/testsuite/g++.dg/modules/dguide-6.h 
> > b/gcc/testsuite/g++.dg/modules/dguide-6.h
> > new file mode 100644
> > index 00000000000..f204af49e8c
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/modules/dguide-6.h
> > @@ -0,0 +1,4 @@
> > +template <typename T> struct S {
> > +  S(int);
> > +  S(int, int);
> > +};
> > diff --git a/gcc/testsuite/g++.dg/modules/dguide-6_a.C 
> > b/gcc/testsuite/g++.dg/modules/dguide-6_a.C
> > new file mode 100644
> > index 00000000000..727336edd90
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/modules/dguide-6_a.C
> > @@ -0,0 +1,7 @@
> > +// { dg-additional-options "-fmodules" }
> > +// { dg-module-cmi M:a }
> > +
> > +module;
> > +#include "dguide-6.h"
> > +export module M:a;
> > +S(int) -> S<int>;
> > diff --git a/gcc/testsuite/g++.dg/modules/dguide-6_b.C 
> > b/gcc/testsuite/g++.dg/modules/dguide-6_b.C
> > new file mode 100644
> > index 00000000000..b101d0e1661
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/modules/dguide-6_b.C
> > @@ -0,0 +1,8 @@
> > +// { dg-additional-options "-fmodules" }
> > +// { dg-module-cmi M }
> > +
> > +module;
> > +#include "dguide-6.h"
> > +export module M;
> > +export import :a;
> > +S(int, int) -> S<double>;
> > diff --git a/gcc/testsuite/g++.dg/modules/dguide-6_c.C 
> > b/gcc/testsuite/g++.dg/modules/dguide-6_c.C
> > new file mode 100644
> > index 00000000000..5da934fbade
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/modules/dguide-6_c.C
> > @@ -0,0 +1,12 @@
> > +// { dg-additional-options "-fmodules" }
> > +
> > +#include "dguide-6.h"
> > +import M;
> > +
> > +int main() {
> > +  S a(1);
> > +  S<int> a_copy = a;
> > +
> > +  S b(2, 3);
> > +  S<double> b_copy = b;
> > +}
> 

Reply via email to