diff options
author | Nathan Sidwell <nathan@acm.org> | 2021-02-17 05:33:45 -0800 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2021-02-17 05:41:37 -0800 |
commit | 24bf79f1798ad1d64812709001d2d11cd3e6849f (patch) | |
tree | c7501157810903d8c2a6afae46e2d83fb0542469 /gcc | |
parent | d46c7e2c546b26d036856cf570694b832d3b1f54 (diff) | |
download | gcc-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.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/pr99116-1.C | 25 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/pr99116-2.C | 19 |
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; |