public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
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
> 


      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).