From: Patrick Palka <ppalka@redhat.com>
To: gcc-patches@gcc.gnu.org
Cc: jason@redhat.com, Patrick Palka <ppalka@redhat.com>
Subject: [PATCH] c++: 'typename T::X' vs 'struct T::X' lookup [PR109420]
Date: Wed, 5 Apr 2023 12:59:27 -0400 [thread overview]
Message-ID: <20230405165927.1987914-1-ppalka@redhat.com> (raw)
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
next reply other threads:[~2023-04-05 16:59 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-05 16:59 Patrick Palka [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230405165927.1987914-1-ppalka@redhat.com \
--to=ppalka@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).