From: Jason Merrill <jason@redhat.com>
To: Marek Polacek <polacek@redhat.com>
Cc: Nathan Sidwell <nathan@acm.org>,
GCC Patches <gcc-patches@gcc.gnu.org>,
Jakub Jelinek <jakub@redhat.com>
Subject: Re: [PATCH v2] c++: ICE with USING_DECL redeclaration [PR98687]
Date: Tue, 19 Jan 2021 16:11:31 -0500 [thread overview]
Message-ID: <57b5f60a-96f3-ec42-6db8-2208932b10af@redhat.com> (raw)
In-Reply-To: <20210119204717.GD29415@redhat.com>
On 1/19/21 3:47 PM, Marek Polacek wrote:
> On Mon, Jan 18, 2021 at 05:18:46PM -0500, Jason Merrill wrote:
>> On 1/15/21 12:26 AM, Marek Polacek wrote:
>>> My recent patch that introduced push_using_decl_bindings didn't
>>> handle USING_DECL redeclaration, therefore things broke. This
>>> patch amends that. Note that I don't know if the other parts of
>>> finish_nonmember_using_decl are needed (e.g. the binding->type
>>> setting) -- I couldn't trigger it by any of my hand-made testcases.
>>
>> I'd expect it to be exercised by something along the lines of
>>
>> struct A { };
>>
>> void f()
>> {
>> int A;
>> using ::A;
>> struct A a;
>> }
>
> Hmm, I already had a test for the struct stat hack, but I've added this one
> to using64.C, thanks.
>
>> Let's factor the code out of finish_nonmember_using_decl rather than copy
>> it.
>
> Done here. A small complication was that name_lookup is local to
> name-lookup.c so I had to add an overload to handle this.
>
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
>
> -- >8 --
> 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.
> ---
> gcc/cp/name-lookup.c | 103 ++++++++++++++------------
> gcc/cp/name-lookup.h | 2 +-
> gcc/cp/pt.c | 3 +-
> gcc/testsuite/g++.dg/lookup/using64.C | 69 +++++++++++++++++
> gcc/testsuite/g++.dg/lookup/using65.C | 17 +++++
> 5 files changed, 145 insertions(+), 49 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/lookup/using64.C
> create mode 100644 gcc/testsuite/g++.dg/lookup/using65.C
>
> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> index b4b6c0b81b5..843e5f305c0 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"
> diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
> index bac3fa71fc9..75db5b38061 100644
> --- a/gcc/cp/name-lookup.h
> +++ b/gcc/cp/name-lookup.h
> @@ -478,7 +478,7 @@ extern void push_to_top_level (void);
> extern void pop_from_top_level (void);
> extern void maybe_save_operator_binding (tree);
> extern void push_operator_bindings (void);
> -extern void push_using_decl_bindings (tree);
> +extern void push_using_decl_bindings (tree, tree);
> extern void discard_operator_bindings (tree);
>
> /* Lower level interface for modules. */
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 957140115e4..12d084031b1 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -18136,7 +18136,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
> == tsubst (scope, args, complain, in_decl));
> /* We still need to push the bindings so that we can look up
> this name later. */
> - push_using_decl_bindings (decl);
> + push_using_decl_bindings (DECL_NAME (decl),
> + USING_DECL_DECLS (decl));
There could still be an overload of push_using_decl_bindings that takes
a single argument. OK either way.
> }
> else if (is_capture_proxy (decl)
> && !DECL_TEMPLATE_INSTANTIATION (current_function_decl))
> diff --git a/gcc/testsuite/g++.dg/lookup/using64.C b/gcc/testsuite/g++.dg/lookup/using64.C
> new file mode 100644
> index 00000000000..a50cd273c89
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/lookup/using64.C
> @@ -0,0 +1,69 @@
> +// PR c++/98687
> +// { dg-do compile }
> +
> +struct S { };
> +
> +namespace N {
> + template <typename T>
> + bool operator==(T, int);
> +
> + template <typename T>
> + void X(T);
> +}
> +
> +namespace M {
> + template <typename T>
> + bool operator==(T, double);
> +}
> +
> +template<typename T>
> +bool fn1 (T t)
> +{
> + using N::operator==;
> + return t == 1;
> +}
> +
> +template<typename T>
> +bool fn2 (T t)
> +{
> + // Redeclaration.
> + using N::operator==;
> + using N::operator==;
> + return t == 1;
> +}
> +
> +template<typename T>
> +bool fn3 (T t)
> +{
> + // Need update_local_overload.
> + using N::operator==;
> + using M::operator==;
> + return t == 1;
> +}
> +
> +template<typename T>
> +void fn4 (T)
> +{
> + struct X { };
> + using N::X;
> + X(1);
> +}
> +
> +template<typename T>
> +void fn5 (T)
> +{
> + int S;
> + using ::S;
> + struct S s;
> +}
> +
> +void
> +g ()
> +{
> + S s;
> + fn1 (s);
> + fn2 (s);
> + fn3 (s);
> + fn4 (s);
> + fn5 (s);
> +}
> diff --git a/gcc/testsuite/g++.dg/lookup/using65.C b/gcc/testsuite/g++.dg/lookup/using65.C
> new file mode 100644
> index 00000000000..bc6c086197f
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/lookup/using65.C
> @@ -0,0 +1,17 @@
> +// PR c++/98687
> +// { dg-do compile }
> +
> +extern "C" namespace std {
> + double log1p(double);
> +}
> +namespace std_fallback {
> + template <typename> void log1p();
> +}
> +template <typename> struct log1p_impl {
> + static int run() {
> + using std::log1p;
> + using std_fallback::log1p;
> + return 0;
> + }
> +};
> +void log1p() { log1p_impl<int>::run(); }
>
> base-commit: 7266ff2a243715e20882850b2fc4211ac7db4d34
>
prev parent reply other threads:[~2021-01-19 21:11 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-15 5:26 [PATCH] " Marek Polacek
2021-01-18 22:18 ` Jason Merrill
2021-01-19 20:47 ` [PATCH v2] " Marek Polacek
2021-01-19 21:11 ` Jason Merrill [this message]
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=57b5f60a-96f3-ec42-6db8-2208932b10af@redhat.com \
--to=jason@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jakub@redhat.com \
--cc=nathan@acm.org \
--cc=polacek@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).