Patchwork C++ PATCH for c++/48647 (wrong common pointer type in SFINAE)

login
register
mail settings
Submitter Jason Merrill
Date May 22, 2011, 6:47 p.m.
Message ID <4DD95A59.40705@redhat.com>
Download mbox | patch
Permalink /patch/96763/
State New
Headers show

Comments

Jason Merrill - May 22, 2011, 6:47 p.m.
The SFINAE code in composite_pointer_type_r correctly avoids giving an 
error in SFINAE context, but then it just uses the permissive fallback 
without indicating to the caller that there was an error, so we get 
wrong results.  This patch fixes it to return error_mark_node when we 
see an error.

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

Patch

commit 8b4f0e86bd63184f63ec3ca0e6960ea9d88f90fa
Author: Jason Merrill <jason@redhat.com>
Date:   Sun May 22 01:15:13 2011 -0400

    	PR c++/48647
    	* typeck.c (composite_pointer_type_r): Return error_mark_node
    	on error in SFINAE context.

diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 7791efc..dd1cc3b 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -516,7 +516,8 @@  composite_pointer_type_r (tree t1, tree t2,
     {
       if (complain & tf_error)
 	composite_pointer_error (DK_PERMERROR, t1, t2, operation);
-
+      else
+	return error_mark_node;
       result_type = void_type_node;
     }
   result_type = cp_build_qualified_type (result_type,
@@ -527,9 +528,13 @@  composite_pointer_type_r (tree t1, tree t2,
   if (TYPE_PTR_TO_MEMBER_P (t1))
     {
       if (!same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1),
-			TYPE_PTRMEM_CLASS_TYPE (t2))
-	  && (complain & tf_error))
-	composite_pointer_error (DK_PERMERROR, t1, t2, operation);
+			TYPE_PTRMEM_CLASS_TYPE (t2)))
+	{
+	  if (complain & tf_error)
+	    composite_pointer_error (DK_PERMERROR, t1, t2, operation);
+	  else
+	    return error_mark_node;
+	}
       result_type = build_ptrmem_type (TYPE_PTRMEM_CLASS_TYPE (t1),
 				       result_type);
     }
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae23.C b/gcc/testsuite/g++.dg/cpp0x/sfinae23.C
new file mode 100644
index 0000000..4e2ea88
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae23.C
@@ -0,0 +1,28 @@ 
+// PR c++/48647
+// { dg-options -std=c++0x }
+
+template< class T >
+T&& declval();
+
+template< class T, class U >
+decltype( true ? declval<T>() : declval<U>() ) test( int );
+
+template< class T, class U >
+void test( ... );
+
+
+template< class T, class U >
+struct is_same {
+  static const bool value = false;
+};
+
+template< class T >
+struct is_same<T, T> {
+  static const bool value = true;
+};
+
+#define SA(X) static_assert ((X),#X)
+
+typedef decltype( test<int*, double*>(0) ) void_expected;
+SA ((is_same<void_expected, void>::value));
+SA ((!is_same<void_expected, void*>::value));
diff --git a/gcc/testsuite/g++.dg/template/sfinae8.C b/gcc/testsuite/g++.dg/template/sfinae8.C
index 2ad68dc..5ac09c6 100644
--- a/gcc/testsuite/g++.dg/template/sfinae8.C
+++ b/gcc/testsuite/g++.dg/template/sfinae8.C
@@ -120,7 +120,7 @@  STATIC_ASSERT((!is_equality_comparable<Y, X>::value));
 STATIC_ASSERT((!is_equality_comparable<Y>::value));
 STATIC_ASSERT((is_equality_comparable<int X::*>::value));
 STATIC_ASSERT((!is_equality_comparable<int X::*, int Y::*>::value));
-STATIC_ASSERT((is_equality_comparable<int*, float*>::value));
+STATIC_ASSERT((!is_equality_comparable<int*, float*>::value));
 STATIC_ASSERT((is_equality_comparable<X*, Z*>::value));
 STATIC_ASSERT((!is_equality_comparable<X*, Y*>::value));
 
@@ -139,7 +139,7 @@  STATIC_ASSERT((!is_not_equal_comparable<Y, X>::value));
 STATIC_ASSERT((!is_not_equal_comparable<Y>::value));
 STATIC_ASSERT((is_not_equal_comparable<int X::*>::value));
 STATIC_ASSERT((!is_not_equal_comparable<int X::*, int Y::*>::value));
-STATIC_ASSERT((is_not_equal_comparable<int*, float*>::value));
+STATIC_ASSERT((!is_not_equal_comparable<int*, float*>::value));
 STATIC_ASSERT((is_not_equal_comparable<X*, Z*>::value));
 STATIC_ASSERT((!is_not_equal_comparable<X*, Y*>::value));