diff mbox series

[pushed] c++: Fix comparison of fn() and ns::fn() [PR90711]

Message ID 20200330211539.7951-1-jason@redhat.com
State New
Headers show
Series [pushed] c++: Fix comparison of fn() and ns::fn() [PR90711] | expand

Commit Message

Li, Pan2 via Gcc-patches March 30, 2020, 9:15 p.m. UTC
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.

Tested x86_64-pc-linux-gnu, applying to trunk/9.

gcc/cp/ChangeLog
2020-03-30  Jason Merrill  <jason@redhat.com>

	PR c++/90711
	* tree.c (cp_tree_equal) [CALL_EXPR]: Compare KOENIG_LOOKUP_P.
	(called_fns_equal): Check DECL_CONTEXT.
---
 gcc/cp/tree.c                                 | 14 ++++++-
 .../g++.dg/template/dependent-name14.C        | 38 +++++++++++++++++++
 2 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/template/dependent-name14.C


base-commit: 1cb1986cb596336e688c079b821205ec212a46a3
diff mbox series

Patch

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<typename... ARGS>
+struct stub_void {
+    typedef void type;
+};
+template<typename... ARGS>
+using stub_void_t = typename stub_void<ARGS...>::type;
+
+#if !defined(SUPPRESS)
+template<typename O, typename = void>
+struct has_to_string {
+    static constexpr bool value = false;
+};
+
+template<typename O>
+struct has_to_string<O, stub_void_t<decltype(EXISTS(O{}))>> {
+    static constexpr bool value = true;
+};
+#endif
+
+template<typename O, typename = void>
+struct has_std_to_string {
+    static constexpr bool value = false;
+};
+
+template<typename O>
+struct has_std_to_string<O, stub_void_t<decltype(test::EXISTS(O{}))>> {
+    static constexpr bool value = true;
+};
+
+static_assert (has_std_to_string<int>::value, "");
+