* [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]
@ 2023-04-05 16:59 Patrick Palka
2023-04-05 17:31 ` Patrick Palka
0 siblings, 1 reply; 7+ messages in thread
From: Patrick Palka @ 2023-04-05 16:59 UTC (permalink / raw)
To: gcc-patches; +Cc: jason, Patrick Palka
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) <case TYPENAME_TYPE>: 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 00000000000..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<class T, class U>
+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<A, B>();
--
2.40.0.153.g6369acd968
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]
2023-04-05 16:59 [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420] Patrick Palka
@ 2023-04-05 17:31 ` Patrick Palka
2023-04-05 17:35 ` Andrew Pinski
2023-04-13 19:09 ` Jason Merrill
0 siblings, 2 replies; 7+ messages in thread
From: Patrick Palka @ 2023-04-05 17:31 UTC (permalink / raw)
To: Patrick Palka; +Cc: gcc-patches, jason
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) <case TYPENAME_TYPE>: 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) <case TYPENAME_TYPE>: 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 'class'
+ tags. TYPENAME_TYPE should probably remember the exact tag that
+ was written. */
+ 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 00000000000..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<class T, class U>
+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<A, B>();
--
2.40.0.153.g6369acd968
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]
2023-04-05 17:31 ` Patrick Palka
@ 2023-04-05 17:35 ` Andrew Pinski
2023-04-18 12:13 ` Patrick Palka
2024-05-03 15:08 ` Patrick Palka
2023-04-13 19:09 ` Jason Merrill
1 sibling, 2 replies; 7+ messages in thread
From: Andrew Pinski @ 2023-04-05 17:35 UTC (permalink / raw)
To: Patrick Palka; +Cc: gcc-patches, jason
On Wed, Apr 5, 2023 at 10:32 AM Patrick Palka via Gcc-patches
<gcc-patches@gcc.gnu.org> 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) <case TYPENAME_TYPE>: 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) <case TYPENAME_TYPE>: 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 'class'
> + tags. TYPENAME_TYPE should probably remember the exact tag that
> + was written. */
Yes I had a patch for that but I submitted during stage 4 of GCC 12
and never updated again during stage 1 of GCC 13. I hope to submit it
again with updated changes post this patch.
Thanks,
Andrew
> + 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 00000000000..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<class T, class U>
> +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<A, B>();
> --
> 2.40.0.153.g6369acd968
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]
2023-04-05 17:31 ` Patrick Palka
2023-04-05 17:35 ` Andrew Pinski
@ 2023-04-13 19:09 ` Jason Merrill
1 sibling, 0 replies; 7+ messages in thread
From: Jason Merrill @ 2023-04-13 19:09 UTC (permalink / raw)
To: Patrick Palka; +Cc: 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) <case TYPENAME_TYPE>: 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) <case TYPENAME_TYPE>: 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 'class'
> + tags. TYPENAME_TYPE should probably remember the exact tag that
> + was written. */
> + 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 00000000000..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<class T, class U>
> +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<A, B>();
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]
2023-04-05 17:35 ` Andrew Pinski
@ 2023-04-18 12:13 ` Patrick Palka
2024-05-03 15:08 ` Patrick Palka
1 sibling, 0 replies; 7+ messages in thread
From: Patrick Palka @ 2023-04-18 12:13 UTC (permalink / raw)
To: Andrew Pinski; +Cc: gcc-patches, jason
On Wed, Apr 5, 2023 at 1:36 PM Andrew Pinski <pinskia@gmail.com> wrote:
>
> On Wed, Apr 5, 2023 at 10:32 AM Patrick Palka via Gcc-patches
> <gcc-patches@gcc.gnu.org> 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) <case TYPENAME_TYPE>: 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) <case TYPENAME_TYPE>: 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 'class'
> > + tags. TYPENAME_TYPE should probably remember the exact tag that
> > + was written. */
>
> Yes I had a patch for that but I submitted during stage 4 of GCC 12
> and never updated again during stage 1 of GCC 13. I hope to submit it
> again with updated changes post this patch.
That'd be great. We could encode all possible tags using three
adjacent TREE_LANG_FLAG bits I think (so just one more bit than what
TYPENAME_TYPE currently uses).
>
> Thanks,
> Andrew
>
>
> > + 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 00000000000..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<class T, class U>
> > +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<A, B>();
> > --
> > 2.40.0.153.g6369acd968
> >
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]
2023-04-05 17:35 ` Andrew Pinski
2023-04-18 12:13 ` Patrick Palka
@ 2024-05-03 15:08 ` Patrick Palka
2024-05-03 20:36 ` Andrew Pinski
1 sibling, 1 reply; 7+ messages in thread
From: Patrick Palka @ 2024-05-03 15:08 UTC (permalink / raw)
To: Andrew Pinski; +Cc: Patrick Palka, gcc-patches, jason
[-- Attachment #1: Type: text/plain, Size: 7307 bytes --]
Hey Andrew,
On Wed, 5 Apr 2023, Andrew Pinski wrote:
> On Wed, Apr 5, 2023 at 10:32 AM Patrick Palka via Gcc-patches
> <gcc-patches@gcc.gnu.org> 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) <case TYPENAME_TYPE>: 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) <case TYPENAME_TYPE>: 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 'class'
> > + tags. TYPENAME_TYPE should probably remember the exact tag that
> > + was written. */
>
> Yes I had a patch for that but I submitted during stage 4 of GCC 12
> and never updated again during stage 1 of GCC 13. I hope to submit it
> again with updated changes post this patch.
Do you still plan on submitting a patch for this? It would be great to
fix this for GCC 15 :)
>
> Thanks,
> Andrew
>
>
> > + 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 00000000000..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<class T, class U>
> > +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<A, B>();
> > --
> > 2.40.0.153.g6369acd968
> >
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]
2024-05-03 15:08 ` Patrick Palka
@ 2024-05-03 20:36 ` Andrew Pinski
0 siblings, 0 replies; 7+ messages in thread
From: Andrew Pinski @ 2024-05-03 20:36 UTC (permalink / raw)
To: Patrick Palka; +Cc: gcc-patches, jason
On Fri, May 3, 2024 at 8:08 AM Patrick Palka <ppalka@redhat.com> 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
> > <gcc-patches@gcc.gnu.org> 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) <case TYPENAME_TYPE>: 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) <case TYPENAME_TYPE>: 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 'class'
> > > + tags. TYPENAME_TYPE should probably remember the exact tag that
> > > + was written. */
> >
> > Yes I had a patch for that but I submitted during stage 4 of GCC 12
> > and never updated again during stage 1 of GCC 13. I hope to submit it
> > again with updated changes post this patch.
>
> Do you still plan on submitting a patch for this? It would be great to
> fix this for GCC 15 :)
I think I will be getting back to that patch the first week of June
and submitting an updated version based on the previous review. I have
a few other patches I am working on before I can start working on that
one.
Thanks,
Andrew
>
> >
> > Thanks,
> > Andrew
> >
> >
> > > + 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 00000000000..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<class T, class U>
> > > +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<A, B>();
> > > --
> > > 2.40.0.153.g6369acd968
> > >
> >
> >
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2024-05-03 20:36 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-05 16:59 [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420] Patrick Palka
2023-04-05 17:31 ` Patrick Palka
2023-04-05 17:35 ` Andrew Pinski
2023-04-18 12:13 ` Patrick Palka
2024-05-03 15:08 ` Patrick Palka
2024-05-03 20:36 ` Andrew Pinski
2023-04-13 19:09 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).