Patchwork C++ PATCH for c++/49045 (core 1321, equivalence of dependent names)

login
register
mail settings
Submitter Jason Merrill
Date Aug. 23, 2011, 3:54 p.m.
Message ID <4E53CD38.2040103@redhat.com>
Download mbox | patch
Permalink /patch/111138/
State New
Headers show

Comments

Jason Merrill - Aug. 23, 2011, 3:54 p.m.
In this PR, g++ was treating two uses of "swap" in a decltype as 
different because the result of unqualified name lookup changed between 
them.  At the meeting last week the committee decided that two dependent 
names should be considered equivalent even if that happens.

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

Patch

commit 00ece4f71ac12eddf4e5c0c44ead47bd2aa41475
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Aug 19 13:08:47 2011 -0400

    	PR c++/49045
    	Core 1321
    	* tree.c (dependent_name): New.
    	(cp_tree_equal): Two calls with the same dependent name are
    	equivalent even if the overload sets are different.

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 00598ce..13421a4 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1450,6 +1450,21 @@  is_overloaded_fn (tree x)
 	   || TREE_CODE (x) == OVERLOAD);
 }
 
+/* X is the CALL_EXPR_FN of a CALL_EXPR.  If X represents a dependent name
+   (14.6.2), return the IDENTIFIER_NODE for that name.  Otherwise, return
+   NULL_TREE.  */
+
+static tree
+dependent_name (tree x)
+{
+  if (TREE_CODE (x) == IDENTIFIER_NODE)
+    return x;
+  if (TREE_CODE (x) != COMPONENT_REF
+      && is_overloaded_fn (x))
+    return DECL_NAME (get_first_fn (x));
+  return NULL_TREE;
+}
+
 /* Returns true iff X is an expression for an overloaded function
    whose type cannot be known without performing overload
    resolution.  */
@@ -2187,7 +2202,12 @@  cp_tree_equal (tree t1, tree t2)
       {
 	tree arg1, arg2;
 	call_expr_arg_iterator iter1, iter2;
-	if (!cp_tree_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
+	/* Core 1321: dependent names are equivalent even if the
+	   overload sets are different.  */
+	tree name1 = dependent_name (CALL_EXPR_FN (t1));
+	tree name2 = dependent_name (CALL_EXPR_FN (t2));
+	if (!(name1 && name2 && name1 == name2)
+	    && !cp_tree_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/cpp0x/overload2.C b/gcc/testsuite/g++.dg/cpp0x/overload2.C
new file mode 100644
index 0000000..ff8ad22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/overload2.C
@@ -0,0 +1,24 @@ 
+// Core 1321
+// { dg-options -std=c++0x }
+// Two dependent names are equivalent even if the overload sets found by
+// phase 1 lookup are different.  Merging them keeps the earlier set.
+
+int g1(int);
+template <class T> decltype(g1(T())) f1();
+int g1();
+template <class T> decltype(g1(T())) f1()
+{ return g1(T()); }
+int i1 = f1<int>();	    // OK, g1(int) was declared before the first f1
+
+template <class T> decltype(g2(T())) f2();
+int g2(int);
+template <class T> decltype(g2(T())) f2() // { dg-error "g2. was not declared" }
+{ return g2(T()); }
+int i2 = f2<int>();			  // { dg-error "no match" }
+
+int g3();
+template <class T> decltype(g3(T())) f3();
+int g3(int);
+template <class T> decltype(g3(T())) f3() // { dg-error "too many arguments" }
+{ return g3(T()); }
+int i3 = f3<int>();			  // { dg-error "no match" }