diff options
author | Marek Polacek <polacek@redhat.com> | 2021-01-13 11:09:14 -0500 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2021-01-13 17:16:30 -0500 |
commit | 796ead19f85372e59217c9888db688a2fe11b54f (patch) | |
tree | 827da19dae4cc952febf76f97a568e2b8ef5219f | |
parent | 8fc183ccd0628465205b8a88c29ab69bfe74a08a (diff) | |
download | gcc-796ead19f85372e59217c9888db688a2fe11b54f.zip gcc-796ead19f85372e59217c9888db688a2fe11b54f.tar.gz gcc-796ead19f85372e59217c9888db688a2fe11b54f.tar.bz2 |
c++: Failure to lookup using-decl name [PR98231]
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.
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.
-rw-r--r-- | gcc/cp/name-lookup.c | 10 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 1 | ||||
-rw-r--r-- | gcc/cp/pt.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/using63.C | 17 |
4 files changed, 31 insertions, 0 deletions
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 5078a07..b4b6c0b 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 7172079..bac3fa7 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 100c35f..c27ef6d 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 0000000..fd4bf26 --- /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); } |