diff options
author | Marek Polacek <polacek@redhat.com> | 2021-01-14 22:14:38 -0500 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2021-01-19 17:13:00 -0500 |
commit | d89b00c095e99cd5cb6d3e05f30d3a61fa592000 (patch) | |
tree | 88c70d0ec39f9ee8978aea8ff133a4deed603301 /gcc/cp/name-lookup.c | |
parent | 9693e255ee2536c6823640eba5d0163c2b401161 (diff) | |
download | gcc-d89b00c095e99cd5cb6d3e05f30d3a61fa592000.zip gcc-d89b00c095e99cd5cb6d3e05f30d3a61fa592000.tar.gz gcc-d89b00c095e99cd5cb6d3e05f30d3a61fa592000.tar.bz2 |
c++: ICE with USING_DECL redeclaration [PR98687]
My recent patch that introduced push_using_decl_bindings didn't
handle USING_DECL redeclaration, therefore things broke. This patch
amends that by breaking out a part of finish_nonmember_using_decl
out to a separate function, push_using_decl_bindings, and calling it.
It needs an overload, because name_lookup is only available inside
of name-lookup.c.
gcc/cp/ChangeLog:
PR c++/98687
* name-lookup.c (push_using_decl_bindings): New, broken out of...
(finish_nonmember_using_decl): ...here.
* name-lookup.h (push_using_decl_bindings): Update declaration.
* pt.c (tsubst_expr): Update the call to push_using_decl_bindings.
gcc/testsuite/ChangeLog:
PR c++/98687
* g++.dg/lookup/using64.C: New test.
* g++.dg/lookup/using65.C: New test.
Diffstat (limited to 'gcc/cp/name-lookup.c')
-rw-r--r-- | gcc/cp/name-lookup.c | 103 |
1 files changed, 56 insertions, 47 deletions
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index b4b6c0b..843e5f3 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -6279,6 +6279,61 @@ pushdecl_namespace_level (tree x, bool hiding) return t; } +/* Wrapper around push_local_binding to push the bindings for + a non-member USING_DECL with NAME and VALUE. LOOKUP, if non-null, + is the result of name lookup during template parsing. */ + +static void +push_using_decl_bindings (name_lookup *lookup, tree name, tree value) +{ + tree type = NULL_TREE; + + cxx_binding *binding = find_local_binding (current_binding_level, name); + if (binding) + { + value = binding->value; + type = binding->type; + } + + /* DR 36 questions why using-decls at function scope may not be + duplicates. Disallow it, as C++11 claimed and PR 20420 + implemented. */ + if (lookup) + do_nonmember_using_decl (*lookup, true, true, &value, &type); + + if (!value) + ; + else if (binding && value == binding->value) + /* Redeclaration of this USING_DECL. */; + else if (binding && binding->value && TREE_CODE (value) == OVERLOAD) + { + /* We already have this binding, so replace it. */ + update_local_overload (IDENTIFIER_BINDING (name), value); + IDENTIFIER_BINDING (name)->value = value; + } + else + /* Install the new binding. */ + push_local_binding (name, value, /*using=*/true); + + if (!type) + ; + else if (binding && type == binding->type) + ; + else + { + push_local_binding (name, type, /*using=*/true); + set_identifier_type_value (name, type); + } +} + +/* Overload for push_using_decl_bindings that doesn't take a name_lookup. */ + +void +push_using_decl_bindings (tree name, tree value) +{ + push_using_decl_bindings (nullptr, name, value); +} + /* Process a using declaration in non-class scope. */ void @@ -6395,43 +6450,7 @@ finish_nonmember_using_decl (tree scope, tree name) else { add_decl_expr (using_decl); - - cxx_binding *binding = find_local_binding (current_binding_level, name); - tree value = NULL; - tree type = NULL; - if (binding) - { - value = binding->value; - type = binding->type; - } - - /* DR 36 questions why using-decls at function scope may not be - duplicates. Disallow it, as C++11 claimed and PR 20420 - implemented. */ - do_nonmember_using_decl (lookup, true, true, &value, &type); - - if (!value) - ; - else if (binding && value == binding->value) - ; - else if (binding && binding->value && TREE_CODE (value) == OVERLOAD) - { - update_local_overload (IDENTIFIER_BINDING (name), value); - IDENTIFIER_BINDING (name)->value = value; - } - else - /* Install the new binding. */ - push_local_binding (name, value, true); - - if (!type) - ; - else if (binding && type == binding->type) - ; - else - { - push_local_binding (name, type, true); - set_identifier_type_value (name, type); - } + push_using_decl_bindings (&lookup, name, NULL_TREE); } } @@ -9279,14 +9298,4 @@ push_operator_bindings () } } -/* Wrapper around push_local_binding to push the bindings for - a non-member USING_DECL DECL that was found during template parsing. */ - -void -push_using_decl_bindings (tree decl) -{ - push_local_binding (DECL_NAME (decl), USING_DECL_DECLS (decl), - /*using*/true); -} - #include "gt-cp-name-lookup.h" |