From 5830f753559f25a5dabcc3507bffa611c6b575a6 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 30 Mar 2020 16:09:43 -0400 Subject: [PATCH] c++: Fix comparison of fn() and ns::fn() [PR90711] The resolution of CWG issue 1321 clarified that when deciding whether two expressions involving template parameters are equivalent, two dependent function calls where the function is named with an unqualified-id are considered to be equivalent if the name is the same, even if unqualified lookup finds different sets of functions. We were wrongly treating qualified-ids the same way, so that EXISTS and test::EXISTS were considered to be equivalent even though they are looking up the name in different scopes. This also causes a mangling bug, but I don't think it's safe to fix that for GCC 10; this patch just fixes the comparison. gcc/cp/ChangeLog 2020-03-30 Jason Merrill PR c++/90711 * tree.c (cp_tree_equal) [CALL_EXPR]: Compare KOENIG_LOOKUP_P. (called_fns_equal): Check DECL_CONTEXT. --- gcc/cp/ChangeLog | 6 +++ gcc/cp/tree.c | 14 ++++++- .../g++.dg/template/dependent-name14.C | 38 +++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/template/dependent-name14.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index be22bc091dd..cc79ece1689 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-03-30 Jason Merrill + + PR c++/90711 + * tree.c (cp_tree_equal) [CALL_EXPR]: Compare KOENIG_LOOKUP_P. + (called_fns_equal): Check DECL_CONTEXT. + 2020-03-30 Jakub Jelinek PR c++/94385 diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index b85967e1bfa..a2172dea0d8 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -2464,6 +2464,8 @@ is_overloaded_fn (tree x) tree dependent_name (tree x) { + /* FIXME a dependent name must be unqualified, but this function doesn't + distinguish between qualified and unqualified identifiers. */ if (identifier_p (x)) return x; if (TREE_CODE (x) == TEMPLATE_ID_EXPR) @@ -3581,6 +3583,15 @@ called_fns_equal (tree t1, tree t2) if (name1 != name2) return false; + /* FIXME dependent_name currently returns an unqualified name regardless + of whether the function was named with a qualified- or unqualified-id. + Until that's fixed, check that we aren't looking at overload sets from + different scopes. */ + if (is_overloaded_fn (t1) && is_overloaded_fn (t2) + && (DECL_CONTEXT (get_first_fn (t1)) + != DECL_CONTEXT (get_first_fn (t2)))) + return false; + if (TREE_CODE (t1) == TEMPLATE_ID_EXPR) targs1 = TREE_OPERAND (t1, 1); if (TREE_CODE (t2) == TEMPLATE_ID_EXPR) @@ -3677,7 +3688,8 @@ cp_tree_equal (tree t1, tree t2) { tree arg1, arg2; call_expr_arg_iterator iter1, iter2; - if (!called_fns_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2))) + if (KOENIG_LOOKUP_P (t1) != KOENIG_LOOKUP_P (t2) + || !called_fns_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2))) return false; for (arg1 = first_call_expr_arg (t1, &iter1), arg2 = first_call_expr_arg (t2, &iter2); diff --git a/gcc/testsuite/g++.dg/template/dependent-name14.C b/gcc/testsuite/g++.dg/template/dependent-name14.C new file mode 100644 index 00000000000..52d2e72be35 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/dependent-name14.C @@ -0,0 +1,38 @@ +// PR c++/90711 +// { dg-do compile { target c++11 } } + +namespace test { + void EXISTS(int); +} + +template +struct stub_void { + typedef void type; +}; +template +using stub_void_t = typename stub_void::type; + +#if !defined(SUPPRESS) +template +struct has_to_string { + static constexpr bool value = false; +}; + +template +struct has_to_string> { + static constexpr bool value = true; +}; +#endif + +template +struct has_std_to_string { + static constexpr bool value = false; +}; + +template +struct has_std_to_string> { + static constexpr bool value = true; +}; + +static_assert (has_std_to_string::value, ""); + -- 2.30.2