Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]

2024-05-03 Thread Andrew Pinski
On Fri, May 3, 2024 at 8:08 AM Patrick Palka  wrote:
>
> Hey Andrew,
>
> On Wed, 5 Apr 2023, Andrew Pinski wrote:
>
> > On Wed, Apr 5, 2023 at 10:32 AM Patrick Palka via Gcc-patches
> >  wrote:
> > >
> > > On Wed, 5 Apr 2023, Patrick Palka wrote:
> > >
> > > > r13-6098-g46711ff8e60d64 made make_typename_type no longer ignore
> > > > non-types during the lookup, unless the TYPENAME_TYPE in question was
> > > > followed by the :: scope resolution operator.  But there is another
> > > > exception to this rule: we need to ignore non-types during the lookup
> > > > also if the TYPENAME_TYPE was named with a tag other than 'typename',
> > > > such as 'struct' or 'enum', as per [dcl.type.elab]/5.
> > > >
> > > > This patch implements this additional exception.  It occurred to me that
> > > > the tf_qualifying_scope flag is probably unnecessary if we'd use the
> > > > scope_type tag more thoroughly, but that requires parser changes that
> > > > are probably too risky at this stage.  (I'm working on addressing the
> > > > FIXME/TODOs here for GCC 14.)
> > > >
> > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> > > > trunk?
> > > >
> > > >   PR c++/109420
> > > >
> > > > gcc/cp/ChangeLog:
> > > >
> > > >   * decl.cc (make_typename_type): Also ignore non-types during
> > > >   the lookup if tag_type is something other than none_type or
> > > >   typename_type.
> > > >   * pt.cc (tsubst) : Pass class_type or
> > > >   enum_type as tag_type to make_typename_type as appropriate
> > > >   instead of always passing typename_type.
> > > >
> > > > gcc/testsuite/ChangeLog:
> > > >
> > > >   * g++.dg/template/typename27.C: New test.
> > > > ---
> > > >  gcc/cp/decl.cc |  9 -
> > > >  gcc/cp/pt.cc   |  9 -
> > > >  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
> > > >  3 files changed, 35 insertions(+), 2 deletions(-)
> > > >  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
> > > >
> > > > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > > > index 5369714f9b3..a0a20c5accc 100644
> > > > --- a/gcc/cp/decl.cc
> > > > +++ b/gcc/cp/decl.cc
> > > > @@ -4307,7 +4307,14 @@ make_typename_type (tree context, tree name, 
> > > > enum tag_types tag_type,
> > > >   lookup will stop when we hit a dependent base.  */
> > > >if (!dependent_scope_p (context))
> > > >  {
> > > > -  bool want_type = (complain & tf_qualifying_scope);
> > > > +  /* As per [dcl.type.elab]/5 and [temp.res.general]/3, ignore 
> > > > non-types if
> > > > +  the tag corresponds to a class-key or 'enum' (or is scope_type), 
> > > > or if
> > > > +  this typename is followed by :: as per 
> > > > [basic.lookup.qual.general]/1.
> > > > +  TODO: If we'd set the scope_type tag accurately on all 
> > > > TYPENAME_TYPEs
> > > > +  that are followed by :: then we wouldn't need the 
> > > > tf_qualifying_scope
> > > > +  flag.  */
> > > > +  bool want_type = (tag_type != none_type && tag_type != 
> > > > typename_type)
> > > > + || (complain & tf_qualifying_scope);
> > >
> > > Here's v2 which just slightly improves this comment.  I reckon 
> > > [basic.lookup.elab]
> > > is a better reference than [dcl.type.elab]/5 for justifying why the
> > > lookup should be type-only for class-key and 'enum' TYPENAME_TYPEs.
> > >
> > > -- >8 --
> > >
> > > PR c++/109420
> > >
> > > gcc/cp/ChangeLog:
> > >
> > > * decl.cc (make_typename_type): Also ignore non-types during the
> > > lookup if tag_type corresponds to an elaborated-type-specifier.
> > > * pt.cc (tsubst) : Pass class_type or
> > > enum_type as tag_type to make_typename_type as appropriate
> > > instead of always passing typename_type.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > > * g++.dg/template/typename27.C: New test.
> > > ---
> > >  gcc/cp/decl.cc | 12 +++-
> > >  gcc/cp/pt.cc   |  9 -
> > >  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
> > >  3 files changed, 38 insertions(+), 2 deletions(-)
> > >  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
> > >
> > > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > > index 5369714f9b3..772c059dc2c 100644
> > > --- a/gcc/cp/decl.cc
> > > +++ b/gcc/cp/decl.cc
> > > @@ -4307,7 +4307,17 @@ make_typename_type (tree context, tree name, enum 
> > > tag_types tag_type,
> > >   lookup will stop when we hit a dependent base.  */
> > >if (!dependent_scope_p (context))
> > >  {
> > > -  bool want_type = (complain & tf_qualifying_scope);
> > > +  /* We generally don't ignore non-types during TYPENAME_TYPE lookup
> > > +(as per [temp.res.general]/3), unless
> > > +  - the tag corresponds to a class-key or 'enum' so
> > > +[basic.lookup.elab] applies, or
> > > +

Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]

2024-05-03 Thread Patrick Palka
Hey Andrew,

On Wed, 5 Apr 2023, Andrew Pinski wrote:

> On Wed, Apr 5, 2023 at 10:32 AM Patrick Palka via Gcc-patches
>  wrote:
> >
> > On Wed, 5 Apr 2023, Patrick Palka wrote:
> >
> > > r13-6098-g46711ff8e60d64 made make_typename_type no longer ignore
> > > non-types during the lookup, unless the TYPENAME_TYPE in question was
> > > followed by the :: scope resolution operator.  But there is another
> > > exception to this rule: we need to ignore non-types during the lookup
> > > also if the TYPENAME_TYPE was named with a tag other than 'typename',
> > > such as 'struct' or 'enum', as per [dcl.type.elab]/5.
> > >
> > > This patch implements this additional exception.  It occurred to me that
> > > the tf_qualifying_scope flag is probably unnecessary if we'd use the
> > > scope_type tag more thoroughly, but that requires parser changes that
> > > are probably too risky at this stage.  (I'm working on addressing the
> > > FIXME/TODOs here for GCC 14.)
> > >
> > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> > > trunk?
> > >
> > >   PR c++/109420
> > >
> > > gcc/cp/ChangeLog:
> > >
> > >   * decl.cc (make_typename_type): Also ignore non-types during
> > >   the lookup if tag_type is something other than none_type or
> > >   typename_type.
> > >   * pt.cc (tsubst) : Pass class_type or
> > >   enum_type as tag_type to make_typename_type as appropriate
> > >   instead of always passing typename_type.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > >   * g++.dg/template/typename27.C: New test.
> > > ---
> > >  gcc/cp/decl.cc |  9 -
> > >  gcc/cp/pt.cc   |  9 -
> > >  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
> > >  3 files changed, 35 insertions(+), 2 deletions(-)
> > >  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
> > >
> > > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > > index 5369714f9b3..a0a20c5accc 100644
> > > --- a/gcc/cp/decl.cc
> > > +++ b/gcc/cp/decl.cc
> > > @@ -4307,7 +4307,14 @@ make_typename_type (tree context, tree name, enum 
> > > tag_types tag_type,
> > >   lookup will stop when we hit a dependent base.  */
> > >if (!dependent_scope_p (context))
> > >  {
> > > -  bool want_type = (complain & tf_qualifying_scope);
> > > +  /* As per [dcl.type.elab]/5 and [temp.res.general]/3, ignore 
> > > non-types if
> > > +  the tag corresponds to a class-key or 'enum' (or is scope_type), 
> > > or if
> > > +  this typename is followed by :: as per 
> > > [basic.lookup.qual.general]/1.
> > > +  TODO: If we'd set the scope_type tag accurately on all 
> > > TYPENAME_TYPEs
> > > +  that are followed by :: then we wouldn't need the 
> > > tf_qualifying_scope
> > > +  flag.  */
> > > +  bool want_type = (tag_type != none_type && tag_type != 
> > > typename_type)
> > > + || (complain & tf_qualifying_scope);
> >
> > Here's v2 which just slightly improves this comment.  I reckon 
> > [basic.lookup.elab]
> > is a better reference than [dcl.type.elab]/5 for justifying why the
> > lookup should be type-only for class-key and 'enum' TYPENAME_TYPEs.
> >
> > -- >8 --
> >
> > PR c++/109420
> >
> > gcc/cp/ChangeLog:
> >
> > * decl.cc (make_typename_type): Also ignore non-types during the
> > lookup if tag_type corresponds to an elaborated-type-specifier.
> > * pt.cc (tsubst) : Pass class_type or
> > enum_type as tag_type to make_typename_type as appropriate
> > instead of always passing typename_type.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/template/typename27.C: New test.
> > ---
> >  gcc/cp/decl.cc | 12 +++-
> >  gcc/cp/pt.cc   |  9 -
> >  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
> >  3 files changed, 38 insertions(+), 2 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
> >
> > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > index 5369714f9b3..772c059dc2c 100644
> > --- a/gcc/cp/decl.cc
> > +++ b/gcc/cp/decl.cc
> > @@ -4307,7 +4307,17 @@ make_typename_type (tree context, tree name, enum 
> > tag_types tag_type,
> >   lookup will stop when we hit a dependent base.  */
> >if (!dependent_scope_p (context))
> >  {
> > -  bool want_type = (complain & tf_qualifying_scope);
> > +  /* We generally don't ignore non-types during TYPENAME_TYPE lookup
> > +(as per [temp.res.general]/3), unless
> > +  - the tag corresponds to a class-key or 'enum' so
> > +[basic.lookup.elab] applies, or
> > +  - the tag corresponds to scope_type or tf_qualifying_scope is
> > +set so [basic.lookup.qual]/1 applies.
> > +TODO: If we'd set/track the scope_type tag thoroughly on all
> > +TYPENAME_TYPEs that are followed by :: then we wouldn't need the
> > +   

Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]

2023-04-18 Thread Patrick Palka via Gcc-patches
On Wed, Apr 5, 2023 at 1:36 PM Andrew Pinski  wrote:
>
> On Wed, Apr 5, 2023 at 10:32 AM Patrick Palka via Gcc-patches
>  wrote:
> >
> > On Wed, 5 Apr 2023, Patrick Palka wrote:
> >
> > > r13-6098-g46711ff8e60d64 made make_typename_type no longer ignore
> > > non-types during the lookup, unless the TYPENAME_TYPE in question was
> > > followed by the :: scope resolution operator.  But there is another
> > > exception to this rule: we need to ignore non-types during the lookup
> > > also if the TYPENAME_TYPE was named with a tag other than 'typename',
> > > such as 'struct' or 'enum', as per [dcl.type.elab]/5.
> > >
> > > This patch implements this additional exception.  It occurred to me that
> > > the tf_qualifying_scope flag is probably unnecessary if we'd use the
> > > scope_type tag more thoroughly, but that requires parser changes that
> > > are probably too risky at this stage.  (I'm working on addressing the
> > > FIXME/TODOs here for GCC 14.)
> > >
> > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> > > trunk?
> > >
> > >   PR c++/109420
> > >
> > > gcc/cp/ChangeLog:
> > >
> > >   * decl.cc (make_typename_type): Also ignore non-types during
> > >   the lookup if tag_type is something other than none_type or
> > >   typename_type.
> > >   * pt.cc (tsubst) : Pass class_type or
> > >   enum_type as tag_type to make_typename_type as appropriate
> > >   instead of always passing typename_type.
> > >
> > > gcc/testsuite/ChangeLog:
> > >
> > >   * g++.dg/template/typename27.C: New test.
> > > ---
> > >  gcc/cp/decl.cc |  9 -
> > >  gcc/cp/pt.cc   |  9 -
> > >  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
> > >  3 files changed, 35 insertions(+), 2 deletions(-)
> > >  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
> > >
> > > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > > index 5369714f9b3..a0a20c5accc 100644
> > > --- a/gcc/cp/decl.cc
> > > +++ b/gcc/cp/decl.cc
> > > @@ -4307,7 +4307,14 @@ make_typename_type (tree context, tree name, enum 
> > > tag_types tag_type,
> > >   lookup will stop when we hit a dependent base.  */
> > >if (!dependent_scope_p (context))
> > >  {
> > > -  bool want_type = (complain & tf_qualifying_scope);
> > > +  /* As per [dcl.type.elab]/5 and [temp.res.general]/3, ignore 
> > > non-types if
> > > +  the tag corresponds to a class-key or 'enum' (or is scope_type), 
> > > or if
> > > +  this typename is followed by :: as per 
> > > [basic.lookup.qual.general]/1.
> > > +  TODO: If we'd set the scope_type tag accurately on all 
> > > TYPENAME_TYPEs
> > > +  that are followed by :: then we wouldn't need the 
> > > tf_qualifying_scope
> > > +  flag.  */
> > > +  bool want_type = (tag_type != none_type && tag_type != 
> > > typename_type)
> > > + || (complain & tf_qualifying_scope);
> >
> > Here's v2 which just slightly improves this comment.  I reckon 
> > [basic.lookup.elab]
> > is a better reference than [dcl.type.elab]/5 for justifying why the
> > lookup should be type-only for class-key and 'enum' TYPENAME_TYPEs.
> >
> > -- >8 --
> >
> > PR c++/109420
> >
> > gcc/cp/ChangeLog:
> >
> > * decl.cc (make_typename_type): Also ignore non-types during the
> > lookup if tag_type corresponds to an elaborated-type-specifier.
> > * pt.cc (tsubst) : Pass class_type or
> > enum_type as tag_type to make_typename_type as appropriate
> > instead of always passing typename_type.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/template/typename27.C: New test.
> > ---
> >  gcc/cp/decl.cc | 12 +++-
> >  gcc/cp/pt.cc   |  9 -
> >  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
> >  3 files changed, 38 insertions(+), 2 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
> >
> > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > index 5369714f9b3..772c059dc2c 100644
> > --- a/gcc/cp/decl.cc
> > +++ b/gcc/cp/decl.cc
> > @@ -4307,7 +4307,17 @@ make_typename_type (tree context, tree name, enum 
> > tag_types tag_type,
> >   lookup will stop when we hit a dependent base.  */
> >if (!dependent_scope_p (context))
> >  {
> > -  bool want_type = (complain & tf_qualifying_scope);
> > +  /* We generally don't ignore non-types during TYPENAME_TYPE lookup
> > +(as per [temp.res.general]/3), unless
> > +  - the tag corresponds to a class-key or 'enum' so
> > +[basic.lookup.elab] applies, or
> > +  - the tag corresponds to scope_type or tf_qualifying_scope is
> > +set so [basic.lookup.qual]/1 applies.
> > +TODO: If we'd set/track the scope_type tag thoroughly on all
> > +TYPENAME_TYPEs that are followed by :: then we wouldn't need the
> > +   

Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]

2023-04-13 Thread Jason Merrill via Gcc-patches

On 4/5/23 13:31, Patrick Palka wrote:

On Wed, 5 Apr 2023, Patrick Palka wrote:


r13-6098-g46711ff8e60d64 made make_typename_type no longer ignore
non-types during the lookup, unless the TYPENAME_TYPE in question was
followed by the :: scope resolution operator.  But there is another
exception to this rule: we need to ignore non-types during the lookup
also if the TYPENAME_TYPE was named with a tag other than 'typename',
such as 'struct' or 'enum', as per [dcl.type.elab]/5.

This patch implements this additional exception.  It occurred to me that
the tf_qualifying_scope flag is probably unnecessary if we'd use the
scope_type tag more thoroughly, but that requires parser changes that
are probably too risky at this stage.  (I'm working on addressing the
FIXME/TODOs here for GCC 14.)

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

PR c++/109420

gcc/cp/ChangeLog:

* decl.cc (make_typename_type): Also ignore non-types during
the lookup if tag_type is something other than none_type or
typename_type.
* pt.cc (tsubst) : Pass class_type or
enum_type as tag_type to make_typename_type as appropriate
instead of always passing typename_type.

gcc/testsuite/ChangeLog:

* g++.dg/template/typename27.C: New test.
---
  gcc/cp/decl.cc |  9 -
  gcc/cp/pt.cc   |  9 -
  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
  3 files changed, 35 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 5369714f9b3..a0a20c5accc 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -4307,7 +4307,14 @@ make_typename_type (tree context, tree name, enum 
tag_types tag_type,
   lookup will stop when we hit a dependent base.  */
if (!dependent_scope_p (context))
  {
-  bool want_type = (complain & tf_qualifying_scope);
+  /* As per [dcl.type.elab]/5 and [temp.res.general]/3, ignore non-types if
+the tag corresponds to a class-key or 'enum' (or is scope_type), or if
+this typename is followed by :: as per [basic.lookup.qual.general]/1.
+TODO: If we'd set the scope_type tag accurately on all TYPENAME_TYPEs
+that are followed by :: then we wouldn't need the tf_qualifying_scope
+flag.  */
+  bool want_type = (tag_type != none_type && tag_type != typename_type)
+   || (complain & tf_qualifying_scope);


Here's v2 which just slightly improves this comment.  I reckon 
[basic.lookup.elab]
is a better reference than [dcl.type.elab]/5 for justifying why the
lookup should be type-only for class-key and 'enum' TYPENAME_TYPEs.


OK, thanks.


-- >8 --

PR c++/109420

gcc/cp/ChangeLog:

* decl.cc (make_typename_type): Also ignore non-types during the
lookup if tag_type corresponds to an elaborated-type-specifier.
* pt.cc (tsubst) : Pass class_type or
enum_type as tag_type to make_typename_type as appropriate
instead of always passing typename_type.

gcc/testsuite/ChangeLog:

* g++.dg/template/typename27.C: New test.
---
  gcc/cp/decl.cc | 12 +++-
  gcc/cp/pt.cc   |  9 -
  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
  3 files changed, 38 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 5369714f9b3..772c059dc2c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -4307,7 +4307,17 @@ make_typename_type (tree context, tree name, enum 
tag_types tag_type,
   lookup will stop when we hit a dependent base.  */
if (!dependent_scope_p (context))
  {
-  bool want_type = (complain & tf_qualifying_scope);
+  /* We generally don't ignore non-types during TYPENAME_TYPE lookup
+(as per [temp.res.general]/3), unless
+  - the tag corresponds to a class-key or 'enum' so
+[basic.lookup.elab] applies, or
+  - the tag corresponds to scope_type or tf_qualifying_scope is
+set so [basic.lookup.qual]/1 applies.
+TODO: If we'd set/track the scope_type tag thoroughly on all
+TYPENAME_TYPEs that are followed by :: then we wouldn't need the
+tf_qualifying_scope flag.  */
+  bool want_type = (tag_type != none_type && tag_type != typename_type)
+   || (complain & tf_qualifying_scope);
t = lookup_member (context, name, /*protect=*/2, want_type, complain);
  }
else
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 821e0035c08..09559c88f29 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16580,9 +16580,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
  return error_mark_node;
  }
  
+	/* FIXME: TYPENAME_IS_CLASS_P conflates 'union' vs 'struct' vs 

Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]

2023-04-05 Thread Andrew Pinski via Gcc-patches
On Wed, Apr 5, 2023 at 10:32 AM Patrick Palka via Gcc-patches
 wrote:
>
> On Wed, 5 Apr 2023, Patrick Palka wrote:
>
> > r13-6098-g46711ff8e60d64 made make_typename_type no longer ignore
> > non-types during the lookup, unless the TYPENAME_TYPE in question was
> > followed by the :: scope resolution operator.  But there is another
> > exception to this rule: we need to ignore non-types during the lookup
> > also if the TYPENAME_TYPE was named with a tag other than 'typename',
> > such as 'struct' or 'enum', as per [dcl.type.elab]/5.
> >
> > This patch implements this additional exception.  It occurred to me that
> > the tf_qualifying_scope flag is probably unnecessary if we'd use the
> > scope_type tag more thoroughly, but that requires parser changes that
> > are probably too risky at this stage.  (I'm working on addressing the
> > FIXME/TODOs here for GCC 14.)
> >
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> > trunk?
> >
> >   PR c++/109420
> >
> > gcc/cp/ChangeLog:
> >
> >   * decl.cc (make_typename_type): Also ignore non-types during
> >   the lookup if tag_type is something other than none_type or
> >   typename_type.
> >   * pt.cc (tsubst) : Pass class_type or
> >   enum_type as tag_type to make_typename_type as appropriate
> >   instead of always passing typename_type.
> >
> > gcc/testsuite/ChangeLog:
> >
> >   * g++.dg/template/typename27.C: New test.
> > ---
> >  gcc/cp/decl.cc |  9 -
> >  gcc/cp/pt.cc   |  9 -
> >  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
> >  3 files changed, 35 insertions(+), 2 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
> >
> > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > index 5369714f9b3..a0a20c5accc 100644
> > --- a/gcc/cp/decl.cc
> > +++ b/gcc/cp/decl.cc
> > @@ -4307,7 +4307,14 @@ make_typename_type (tree context, tree name, enum 
> > tag_types tag_type,
> >   lookup will stop when we hit a dependent base.  */
> >if (!dependent_scope_p (context))
> >  {
> > -  bool want_type = (complain & tf_qualifying_scope);
> > +  /* As per [dcl.type.elab]/5 and [temp.res.general]/3, ignore 
> > non-types if
> > +  the tag corresponds to a class-key or 'enum' (or is scope_type), or 
> > if
> > +  this typename is followed by :: as per [basic.lookup.qual.general]/1.
> > +  TODO: If we'd set the scope_type tag accurately on all TYPENAME_TYPEs
> > +  that are followed by :: then we wouldn't need the tf_qualifying_scope
> > +  flag.  */
> > +  bool want_type = (tag_type != none_type && tag_type != typename_type)
> > + || (complain & tf_qualifying_scope);
>
> Here's v2 which just slightly improves this comment.  I reckon 
> [basic.lookup.elab]
> is a better reference than [dcl.type.elab]/5 for justifying why the
> lookup should be type-only for class-key and 'enum' TYPENAME_TYPEs.
>
> -- >8 --
>
> PR c++/109420
>
> gcc/cp/ChangeLog:
>
> * decl.cc (make_typename_type): Also ignore non-types during the
> lookup if tag_type corresponds to an elaborated-type-specifier.
> * pt.cc (tsubst) : Pass class_type or
> enum_type as tag_type to make_typename_type as appropriate
> instead of always passing typename_type.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/template/typename27.C: New test.
> ---
>  gcc/cp/decl.cc | 12 +++-
>  gcc/cp/pt.cc   |  9 -
>  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
>  3 files changed, 38 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
>
> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> index 5369714f9b3..772c059dc2c 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -4307,7 +4307,17 @@ make_typename_type (tree context, tree name, enum 
> tag_types tag_type,
>   lookup will stop when we hit a dependent base.  */
>if (!dependent_scope_p (context))
>  {
> -  bool want_type = (complain & tf_qualifying_scope);
> +  /* We generally don't ignore non-types during TYPENAME_TYPE lookup
> +(as per [temp.res.general]/3), unless
> +  - the tag corresponds to a class-key or 'enum' so
> +[basic.lookup.elab] applies, or
> +  - the tag corresponds to scope_type or tf_qualifying_scope is
> +set so [basic.lookup.qual]/1 applies.
> +TODO: If we'd set/track the scope_type tag thoroughly on all
> +TYPENAME_TYPEs that are followed by :: then we wouldn't need the
> +tf_qualifying_scope flag.  */
> +  bool want_type = (tag_type != none_type && tag_type != typename_type)
> +   || (complain & tf_qualifying_scope);
>t = lookup_member (context, name, /*protect=*/2, want_type, complain);
>  }
>else
> diff --git a/gcc/cp/pt.cc 

Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]

2023-04-05 Thread Patrick Palka via Gcc-patches
On Wed, 5 Apr 2023, Patrick Palka wrote:

> r13-6098-g46711ff8e60d64 made make_typename_type no longer ignore
> non-types during the lookup, unless the TYPENAME_TYPE in question was
> followed by the :: scope resolution operator.  But there is another
> exception to this rule: we need to ignore non-types during the lookup
> also if the TYPENAME_TYPE was named with a tag other than 'typename',
> such as 'struct' or 'enum', as per [dcl.type.elab]/5.
> 
> This patch implements this additional exception.  It occurred to me that
> the tf_qualifying_scope flag is probably unnecessary if we'd use the
> scope_type tag more thoroughly, but that requires parser changes that
> are probably too risky at this stage.  (I'm working on addressing the
> FIXME/TODOs here for GCC 14.)
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?
> 
>   PR c++/109420
> 
> gcc/cp/ChangeLog:
> 
>   * decl.cc (make_typename_type): Also ignore non-types during
>   the lookup if tag_type is something other than none_type or
>   typename_type.
>   * pt.cc (tsubst) : Pass class_type or
>   enum_type as tag_type to make_typename_type as appropriate
>   instead of always passing typename_type.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/template/typename27.C: New test.
> ---
>  gcc/cp/decl.cc |  9 -
>  gcc/cp/pt.cc   |  9 -
>  gcc/testsuite/g++.dg/template/typename27.C | 19 +++
>  3 files changed, 35 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/template/typename27.C
> 
> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> index 5369714f9b3..a0a20c5accc 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -4307,7 +4307,14 @@ make_typename_type (tree context, tree name, enum 
> tag_types tag_type,
>   lookup will stop when we hit a dependent base.  */
>if (!dependent_scope_p (context))
>  {
> -  bool want_type = (complain & tf_qualifying_scope);
> +  /* As per [dcl.type.elab]/5 and [temp.res.general]/3, ignore non-types 
> if
> +  the tag corresponds to a class-key or 'enum' (or is scope_type), or if
> +  this typename is followed by :: as per [basic.lookup.qual.general]/1.
> +  TODO: If we'd set the scope_type tag accurately on all TYPENAME_TYPEs
> +  that are followed by :: then we wouldn't need the tf_qualifying_scope
> +  flag.  */
> +  bool want_type = (tag_type != none_type && tag_type != typename_type)
> + || (complain & tf_qualifying_scope);

Here's v2 which just slightly improves this comment.  I reckon 
[basic.lookup.elab]
is a better reference than [dcl.type.elab]/5 for justifying why the
lookup should be type-only for class-key and 'enum' TYPENAME_TYPEs.

-- >8 --

PR c++/109420

gcc/cp/ChangeLog:

* decl.cc (make_typename_type): Also ignore non-types during the
lookup if tag_type corresponds to an elaborated-type-specifier.
* pt.cc (tsubst) : Pass class_type or
enum_type as tag_type to make_typename_type as appropriate
instead of always passing typename_type.

gcc/testsuite/ChangeLog:

* g++.dg/template/typename27.C: New test.
---
 gcc/cp/decl.cc | 12 +++-
 gcc/cp/pt.cc   |  9 -
 gcc/testsuite/g++.dg/template/typename27.C | 19 +++
 3 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/typename27.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 5369714f9b3..772c059dc2c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -4307,7 +4307,17 @@ make_typename_type (tree context, tree name, enum 
tag_types tag_type,
  lookup will stop when we hit a dependent base.  */
   if (!dependent_scope_p (context))
 {
-  bool want_type = (complain & tf_qualifying_scope);
+  /* We generally don't ignore non-types during TYPENAME_TYPE lookup
+(as per [temp.res.general]/3), unless
+  - the tag corresponds to a class-key or 'enum' so
+[basic.lookup.elab] applies, or
+  - the tag corresponds to scope_type or tf_qualifying_scope is
+set so [basic.lookup.qual]/1 applies.
+TODO: If we'd set/track the scope_type tag thoroughly on all
+TYPENAME_TYPEs that are followed by :: then we wouldn't need the
+tf_qualifying_scope flag.  */
+  bool want_type = (tag_type != none_type && tag_type != typename_type)
+   || (complain & tf_qualifying_scope);
   t = lookup_member (context, name, /*protect=*/2, want_type, complain);
 }
   else
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 821e0035c08..09559c88f29 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16580,9 +16580,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
  return error_mark_node;
  }
 
+   /* FIXME: TYPENAME_IS_CLASS_P conflates 'union' vs 

[PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]

2023-04-05 Thread Patrick Palka via Gcc-patches
r13-6098-g46711ff8e60d64 made make_typename_type no longer ignore
non-types during the lookup, unless the TYPENAME_TYPE in question was
followed by the :: scope resolution operator.  But there is another
exception to this rule: we need to ignore non-types during the lookup
also if the TYPENAME_TYPE was named with a tag other than 'typename',
such as 'struct' or 'enum', as per [dcl.type.elab]/5.

This patch implements this additional exception.  It occurred to me that
the tf_qualifying_scope flag is probably unnecessary if we'd use the
scope_type tag more thoroughly, but that requires parser changes that
are probably too risky at this stage.  (I'm working on addressing the
FIXME/TODOs here for GCC 14.)

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

PR c++/109420

gcc/cp/ChangeLog:

* decl.cc (make_typename_type): Also ignore non-types during
the lookup if tag_type is something other than none_type or
typename_type.
* pt.cc (tsubst) : Pass class_type or
enum_type as tag_type to make_typename_type as appropriate
instead of always passing typename_type.

gcc/testsuite/ChangeLog:

* g++.dg/template/typename27.C: New test.
---
 gcc/cp/decl.cc |  9 -
 gcc/cp/pt.cc   |  9 -
 gcc/testsuite/g++.dg/template/typename27.C | 19 +++
 3 files changed, 35 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/typename27.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 5369714f9b3..a0a20c5accc 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -4307,7 +4307,14 @@ make_typename_type (tree context, tree name, enum 
tag_types tag_type,
  lookup will stop when we hit a dependent base.  */
   if (!dependent_scope_p (context))
 {
-  bool want_type = (complain & tf_qualifying_scope);
+  /* As per [dcl.type.elab]/5 and [temp.res.general]/3, ignore non-types if
+the tag corresponds to a class-key or 'enum' (or is scope_type), or if
+this typename is followed by :: as per [basic.lookup.qual.general]/1.
+TODO: If we'd set the scope_type tag accurately on all TYPENAME_TYPEs
+that are followed by :: then we wouldn't need the tf_qualifying_scope
+flag.  */
+  bool want_type = (tag_type != none_type && tag_type != typename_type)
+   || (complain & tf_qualifying_scope);
   t = lookup_member (context, name, /*protect=*/2, want_type, complain);
 }
   else
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 821e0035c08..1e778e6e786 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -16580,9 +16580,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
  return error_mark_node;
  }
 
+   /* FIXME: TYPENAME_IS_CLASS_P conflates 'union' vs 'struct' vs 'class'
+  tags.  TYPENAME_TYPE should probably remember the exact tag that
+  was used.  */
+   enum tag_types tag
+ = TYPENAME_IS_CLASS_P (t) ? class_type
+ : TYPENAME_IS_ENUM_P (t) ? enum_type
+ : typename_type;
tsubst_flags_t tcomplain = complain | tf_keep_type_decl;
tcomplain |= tst_ok_flag | qualifying_scope_flag;
-   f = make_typename_type (ctx, f, typename_type, tcomplain);
+   f = make_typename_type (ctx, f, tag, tcomplain);
if (f == error_mark_node)
  return f;
if (TREE_CODE (f) == TYPE_DECL)
diff --git a/gcc/testsuite/g++.dg/template/typename27.C 
b/gcc/testsuite/g++.dg/template/typename27.C
new file mode 100644
index 000..61b3efd998e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typename27.C
@@ -0,0 +1,19 @@
+// PR c++/109420
+
+struct A {
+  struct X { };
+  int X;
+};
+
+struct B {
+  enum E { };
+  enum F { E };
+};
+
+template
+void f() {
+  struct T::X x; // OK, lookup ignores the data member 'int A::X'
+  enum U::E e;   // OK, lookup ignores the enumerator 'B::F::E'
+}
+
+template void f();
-- 
2.40.0.153.g6369acd968