* [PATCH] c++: ICE with USING_DECL redeclaration [PR98687]
@ 2021-01-15 5:26 Marek Polacek
2021-01-18 22:18 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Marek Polacek @ 2021-01-15 5:26 UTC (permalink / raw)
To: Jason Merrill, Nathan Sidwell, GCC Patches
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.
Sorry for not thinking harder about redeclarations in the original
patch :(.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
gcc/cp/ChangeLog:
PR c++/98687
* name-lookup.c (push_using_decl_bindings): If we found an
existing local binding, update it if it's not identical.
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 | 20 ++++++++-
gcc/testsuite/g++.dg/lookup/using64.C | 60 +++++++++++++++++++++++++++
gcc/testsuite/g++.dg/lookup/using65.C | 17 ++++++++
3 files changed, 95 insertions(+), 2 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..857d90914ca 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -9285,8 +9285,24 @@ push_operator_bindings ()
void
push_using_decl_bindings (tree decl)
{
- push_local_binding (DECL_NAME (decl), USING_DECL_DECLS (decl),
- /*using*/true);
+ tree name = DECL_NAME (decl);
+ tree value = USING_DECL_DECLS (decl);
+
+ cxx_binding *binding = find_local_binding (current_binding_level, name);
+ if (binding)
+ {
+ if (value == binding->value)
+ /* Redeclaration of this USING_DECL. */;
+ else if (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 (DECL_NAME (decl), value, /*using*/true);
}
#include "gt-cp-name-lookup.h"
diff --git a/gcc/testsuite/g++.dg/lookup/using64.C b/gcc/testsuite/g++.dg/lookup/using64.C
new file mode 100644
index 00000000000..42bce331e19
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using64.C
@@ -0,0 +1,60 @@
+// 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 t)
+{
+ struct X { };
+ using N::X;
+ X(1);
+}
+
+void
+g ()
+{
+ S s;
+ fn1 (s);
+ fn2 (s);
+ fn3 (s);
+ fn4 (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: 5fff80fd79c36a1a940b331d20905061d61ee5e6
--
2.29.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] c++: ICE with USING_DECL redeclaration [PR98687]
2021-01-15 5:26 [PATCH] c++: ICE with USING_DECL redeclaration [PR98687] Marek Polacek
@ 2021-01-18 22:18 ` Jason Merrill
2021-01-19 20:47 ` [PATCH v2] " Marek Polacek
0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2021-01-18 22:18 UTC (permalink / raw)
To: Marek Polacek, Nathan Sidwell, GCC Patches; +Cc: Jakub Jelinek
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;
}
Let's factor the code out of finish_nonmember_using_decl rather than
copy it.
> Sorry for not thinking harder about redeclarations in the original
> patch :(.
>
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
>
> gcc/cp/ChangeLog:
>
> PR c++/98687
> * name-lookup.c (push_using_decl_bindings): If we found an
> existing local binding, update it if it's not identical.
>
> 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 | 20 ++++++++-
> gcc/testsuite/g++.dg/lookup/using64.C | 60 +++++++++++++++++++++++++++
> gcc/testsuite/g++.dg/lookup/using65.C | 17 ++++++++
> 3 files changed, 95 insertions(+), 2 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..857d90914ca 100644
> --- a/gcc/cp/name-lookup.c
> +++ b/gcc/cp/name-lookup.c
> @@ -9285,8 +9285,24 @@ push_operator_bindings ()
> void
> push_using_decl_bindings (tree decl)
> {
> - push_local_binding (DECL_NAME (decl), USING_DECL_DECLS (decl),
> - /*using*/true);
> + tree name = DECL_NAME (decl);
> + tree value = USING_DECL_DECLS (decl);
> +
> + cxx_binding *binding = find_local_binding (current_binding_level, name);
> + if (binding)
> + {
> + if (value == binding->value)
> + /* Redeclaration of this USING_DECL. */;
> + else if (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 (DECL_NAME (decl), value, /*using*/true);
> }
>
> #include "gt-cp-name-lookup.h"
> diff --git a/gcc/testsuite/g++.dg/lookup/using64.C b/gcc/testsuite/g++.dg/lookup/using64.C
> new file mode 100644
> index 00000000000..42bce331e19
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/lookup/using64.C
> @@ -0,0 +1,60 @@
> +// 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 t)
> +{
> + struct X { };
> + using N::X;
> + X(1);
> +}
> +
> +void
> +g ()
> +{
> + S s;
> + fn1 (s);
> + fn2 (s);
> + fn3 (s);
> + fn4 (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: 5fff80fd79c36a1a940b331d20905061d61ee5e6
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] c++: ICE with USING_DECL redeclaration [PR98687]
2021-01-18 22:18 ` Jason Merrill
@ 2021-01-19 20:47 ` Marek Polacek
2021-01-19 21:11 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Marek Polacek @ 2021-01-19 20:47 UTC (permalink / raw)
To: Jason Merrill; +Cc: Nathan Sidwell, GCC Patches, Jakub Jelinek
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));
}
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
--
2.29.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] c++: ICE with USING_DECL redeclaration [PR98687]
2021-01-19 20:47 ` [PATCH v2] " Marek Polacek
@ 2021-01-19 21:11 ` Jason Merrill
0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2021-01-19 21:11 UTC (permalink / raw)
To: Marek Polacek; +Cc: Nathan Sidwell, GCC Patches, Jakub Jelinek
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
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-01-19 21:11 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-15 5:26 [PATCH] c++: ICE with USING_DECL redeclaration [PR98687] 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 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).