aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2021-02-17 05:33:45 -0800
committerNathan Sidwell <nathan@acm.org>2021-02-17 05:41:37 -0800
commit24bf79f1798ad1d64812709001d2d11cd3e6849f (patch)
treec7501157810903d8c2a6afae46e2d83fb0542469 /gcc
parentd46c7e2c546b26d036856cf570694b832d3b1f54 (diff)
downloadgcc-24bf79f1798ad1d64812709001d2d11cd3e6849f.zip
gcc-24bf79f1798ad1d64812709001d2d11cd3e6849f.tar.gz
gcc-24bf79f1798ad1d64812709001d2d11cd3e6849f.tar.bz2
c++: More set_identifier_type_value fixing [PR 99116]
My recent change looked under template_parms in two places, but that was covering up a separate problem. We were attempting to set the identifier_type_value of a template_parm into the template_parm scope. The peeking stopped us doing that, but confused poplevel, leaving an identifier value lying around. This fixes the underlying problem in do_pushtag -- we only need to set the identifier_type_value directly when we're in a template_parm scope (a later pushdecl will push the actual template_decl). for non-class non-template-parm bindings do_pushdecl already ends up manipulating identifier_type_value correctly. PR c++/99116 gcc/cp/ * name-lookup.c (do_pushdecl): Don't peek under template_parm bindings here ... (set_identifier_type_value_with_scope): ... or here. (do_pushtag): Only set_identifier_type_value_with_scope at non-class template parm scope, and use parent scope. gcc/testsuite/ * g++.dg/lookup/pr99116-1.C: New. * g++.dg/lookup/pr99116-2.C: New.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/name-lookup.c32
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr99116-1.C25
-rw-r--r--gcc/testsuite/g++.dg/lookup/pr99116-2.C19
3 files changed, 58 insertions, 18 deletions
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index fda987e..6a4c106 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3691,14 +3691,9 @@ do_pushdecl (tree decl, bool hiding)
if (match == error_mark_node)
;
else if (TREE_CODE (match) == TYPE_DECL)
- {
- auto *l = level;
- while (l->kind == sk_template_parms)
- l = l->level_chain;
- gcc_checking_assert (REAL_IDENTIFIER_TYPE_VALUE (name)
- == (l->kind == sk_namespace
- ? NULL_TREE : TREE_TYPE (match)));
- }
+ gcc_checking_assert (REAL_IDENTIFIER_TYPE_VALUE (name)
+ == (level->kind == sk_namespace
+ ? NULL_TREE : TREE_TYPE (match)));
else if (iter.hidden_p () && !hiding)
{
/* Unhiding a previously hidden decl. */
@@ -4756,12 +4751,13 @@ print_binding_stack (void)
static void
set_identifier_type_value_with_scope (tree id, tree decl, cp_binding_level *b)
{
- while (b->kind == sk_template_parms)
- b = b->level_chain;
-
if (b->kind == sk_namespace)
/* At namespace scope we should not see an identifier type value. */
- gcc_checking_assert (!REAL_IDENTIFIER_TYPE_VALUE (id));
+ gcc_checking_assert (!REAL_IDENTIFIER_TYPE_VALUE (id)
+ /* We could be pushing a friend underneath a template
+ parm (ill-formed). */
+ || (TEMPLATE_PARM_P
+ (TYPE_NAME (REAL_IDENTIFIER_TYPE_VALUE (id)))));
else
{
/* Push the current type value, so we can restore it later */
@@ -8257,10 +8253,8 @@ do_pushtag (tree name, tree type, TAG_how how)
if (decl == error_mark_node)
return decl;
- bool in_class = false;
if (b->kind == sk_class)
{
- in_class = true;
if (!TYPE_BEING_DEFINED (current_class_type))
/* Don't push anywhere if the class is complete; a lambda in an
NSDMI is not a member of the class. */
@@ -8275,7 +8269,12 @@ do_pushtag (tree name, tree type, TAG_how how)
pushdecl_class_level (decl);
}
else if (b->kind == sk_template_parms)
- in_class = b->level_chain->kind == sk_class;
+ {
+ /* Do not push the tag here -- we'll want to push the
+ TEMPLATE_DECL. */
+ if (b->level_chain->kind != sk_class)
+ set_identifier_type_value_with_scope (name, tdef, b->level_chain);
+ }
else
{
decl = do_pushdecl_with_scope
@@ -8293,9 +8292,6 @@ do_pushtag (tree name, tree type, TAG_how how)
}
}
- if (!in_class)
- set_identifier_type_value_with_scope (name, tdef, b);
-
TYPE_CONTEXT (type) = DECL_CONTEXT (decl);
/* If this is a local class, keep track of it. We need this
diff --git a/gcc/testsuite/g++.dg/lookup/pr99116-1.C b/gcc/testsuite/g++.dg/lookup/pr99116-1.C
new file mode 100644
index 0000000..01b483e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/pr99116-1.C
@@ -0,0 +1,25 @@
+// PR 99116 sliding hidden friends under template parm scopes
+
+template<int T> struct Z {
+
+ friend struct T; // { dg-error "shadows template parameter" }
+};
+
+struct Y {
+
+ template<typename S> struct A {};
+
+ friend struct S;
+};
+
+struct X
+{
+ struct S2 {};
+
+ struct In
+ {
+ friend struct S2;
+ };
+};
+
+typedef int S2;
diff --git a/gcc/testsuite/g++.dg/lookup/pr99116-2.C b/gcc/testsuite/g++.dg/lookup/pr99116-2.C
new file mode 100644
index 0000000..2a4148b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/pr99116-2.C
@@ -0,0 +1,19 @@
+// PR 99116, we need to remove the namespace-scope meaning of
+// IDENTIFIER_TYPE_VALUE.
+
+namespace __gnu_cxx
+{
+template<typename _CharT>
+struct char_traits
+{
+ static void length();
+};
+
+template<typename _T>
+void char_traits<_T>::length ()
+{
+}
+
+}
+
+struct char_traits;