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