diff mbox series

c++: Failure to lookup using-decl name [PR98231]

Message ID 20210113183824.653139-1-polacek@redhat.com
State New
Headers show
Series c++: Failure to lookup using-decl name [PR98231] | expand

Commit Message

Marek Polacek Jan. 13, 2021, 6:38 p.m. UTC
In r11-4690 we removed the call to finish_nonmember_using_decl in
tsubst_expr/DECL_EXPR in the USING_DECL block.  This was done not
to perform name lookup twice for a non-dependent using-decl, which
sounds sensible.

However, finish_nonmember_using_decl also pushes the decl's bindings
which we still have to do so that we can find the USING_DECL's name
later.  In this case, we've got a USING_DECL N::operator<<  that we are
tsubstituting.  We already looked it up while parsing the template
"foo", and lookup_using_decl stashed the OVERLOAD it found into
USING_DECL_DECLS.  Now we just have to update the IDENTIFIER_BINDING of
the identifier for operator<< with the overload the name is bound to.

I didn't want to export push_local_binding so I've introduced a new
wrapper.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

gcc/cp/ChangeLog:

	PR c++/98231
	* name-lookup.c (push_using_decl_bindings): New.
	* name-lookup.h (push_using_decl_bindings): Declare.
	* pt.c (tsubst_expr): Call push_using_decl_bindings.

gcc/testsuite/ChangeLog:

	PR c++/98231
	* g++.dg/lookup/using63.C: New test.
---
 gcc/cp/name-lookup.c                  | 10 ++++++++++
 gcc/cp/name-lookup.h                  |  1 +
 gcc/cp/pt.c                           |  3 +++
 gcc/testsuite/g++.dg/lookup/using63.C | 17 +++++++++++++++++
 4 files changed, 31 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/lookup/using63.C


base-commit: 285fa338b06b804e72997c4d876ecf08a9c083af

Comments

Nathan Sidwell Jan. 13, 2021, 10:12 p.m. UTC | #1
On 1/13/21 1:38 PM, Marek Polacek wrote:
> In r11-4690 we removed the call to finish_nonmember_using_decl in
> tsubst_expr/DECL_EXPR in the USING_DECL block.  This was done not
> to perform name lookup twice for a non-dependent using-decl, which
> sounds sensible.
> 
> However, finish_nonmember_using_decl also pushes the decl's bindings
> which we still have to do so that we can find the USING_DECL's name
> later.  In this case, we've got a USING_DECL N::operator<<  that we are
> tsubstituting.  We already looked it up while parsing the template
> "foo", and lookup_using_decl stashed the OVERLOAD it found into
> USING_DECL_DECLS.  Now we just have to update the IDENTIFIER_BINDING of
> the identifier for operator<< with the overload the name is bound to.
> 
> I didn't want to export push_local_binding so I've introduced a new
> wrapper.

seems reasonable
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

ok
diff mbox series

Patch

diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 5078a0706b9..b4b6c0b81b5 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -9279,4 +9279,14 @@  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 7172079b274..bac3fa71fc9 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -478,6 +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 discard_operator_bindings (tree);
 
 /* Lower level interface for modules. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 100c35f053c..c27ef6d9fe0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -18133,6 +18133,9 @@  tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 	    tree scope = USING_DECL_SCOPE (decl);
 	    gcc_checking_assert (scope
 				 == 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);
 	  }
 	else if (is_capture_proxy (decl)
 		 && !DECL_TEMPLATE_INSTANTIATION (current_function_decl))
diff --git a/gcc/testsuite/g++.dg/lookup/using63.C b/gcc/testsuite/g++.dg/lookup/using63.C
new file mode 100644
index 00000000000..fd4bf26f1ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using63.C
@@ -0,0 +1,17 @@ 
+// PR c++/98231
+// { dg-do compile }
+
+template <typename, typename = int> struct basic_ostream {};
+namespace N {
+  template <typename Char, typename CharTraits, typename T>
+  void operator<<(basic_ostream<Char, CharTraits>, T);
+}
+basic_ostream<char> os;
+
+template<typename T> void
+foo (T value)
+{
+  using N::operator<<;
+  os << value;
+}
+void bar() { foo (1); }