Patchwork [C++] Fix PR 44907 (SFINAE vs ambiguous base)

login
register
mail settings
Submitter Paolo Carlini
Date July 12, 2010, 3:34 p.m.
Message ID <4C3B35F6.2030209@oracle.com>
Download mbox | patch
Permalink /patch/58624/
State New
Headers show

Comments

Paolo Carlini - July 12, 2010, 3:34 p.m.
Hi,

this is a fix for the first SFINAE issue noticed while drafting
__is_convertible_to. Tested x86_64-linux. Ok for mainline?

Thanks,
Paolo.

///////////////////////
/cp
2010-07-12  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/44907
	* call.c (build_temp): Add tsubst_flags_t complain parameter;
	adjust build_special_member_call, pass complain.
	(convert_like_real): Adjust build_temp call, pass complain.

/testsuite
2010-07-12  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/44907
	* g++.dg/template/sfinae19.C: New.
	* g++.dg/template/sfinae20.C: Likewise.
Jason Merrill - July 12, 2010, 7:33 p.m.
OK.

Jason

Patch

Index: testsuite/g++.dg/template/sfinae20.C
===================================================================
--- testsuite/g++.dg/template/sfinae20.C	(revision 0)
+++ testsuite/g++.dg/template/sfinae20.C	(revision 0)
@@ -0,0 +1,45 @@ 
+// PR c++/44907
+// { dg-options "-std=c++0x" }
+
+#include <utility>
+
+struct A { };
+
+struct B
+: public A { };
+
+struct C
+: public A { };
+
+struct D
+: public B, public C { };
+
+template<typename From, typename To>
+  class mini_is_convertible
+  {
+    typedef char one;
+    typedef struct { char arr[2]; } two;
+
+    template<typename To1>
+      static void test_aux(To1);
+
+    template<typename To1, typename From1>
+      static decltype(test_aux<To1>(std::declval<From1>()), one())
+      test(int);
+
+    template<typename, typename>
+      static two test(...);
+
+    public:
+      static const bool value = sizeof(test<To, From>(0)) == 1;
+  }; 
+
+template<typename From, typename To>
+  const bool mini_is_convertible<From, To>::value;
+
+static_assert (!mini_is_convertible<D*, A*>::value, "");
+static_assert (!mini_is_convertible<A*, D*>::value, "");
+static_assert (!mini_is_convertible<D&, A&>::value, "");
+static_assert (!mini_is_convertible<A&, D&>::value, "");
+static_assert (!mini_is_convertible<D, A>::value, "");
+static_assert (!mini_is_convertible<A, D>::value, "");
Index: testsuite/g++.dg/template/sfinae19.C
===================================================================
--- testsuite/g++.dg/template/sfinae19.C	(revision 0)
+++ testsuite/g++.dg/template/sfinae19.C	(revision 0)
@@ -0,0 +1,44 @@ 
+// PR c++/44907
+
+struct A { };
+
+struct B
+: public A { };
+
+struct C
+: public A { };
+
+struct D
+: public B, public C { };
+
+template<bool, typename T = void> struct enable_if { typedef T type; };
+template<typename T> struct enable_if<false, T> { };
+
+template<typename From, typename To>
+  class mini_is_convertible
+  {
+    typedef char one;
+    typedef struct { char arr[2]; } two;
+
+    template<typename To1>
+      static void test_aux(To1);
+
+    template<typename To1, typename From1>
+      static typename
+      enable_if<(sizeof(test_aux<To1>(From1()), 1) > 0), one>::type
+      test(int);
+
+    template<typename, typename>
+      static two test(...);
+
+    public:
+      static const bool value = sizeof(test<To, From>(0)) == 1;
+  }; 
+
+template<typename From, typename To>
+  const bool mini_is_convertible<From, To>::value;
+
+int Test1[mini_is_convertible<D*, A*>::value ? -1 : 1]; 
+int Test2[mini_is_convertible<A*, D*>::value ? -1 : 1];
+int Test3[mini_is_convertible<D, A>::value ? -1 : 1]; 
+int Test4[mini_is_convertible<A, D>::value ? -1 : 1];
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 162079)
+++ cp/call.c	(working copy)
@@ -204,7 +204,7 @@  static void add_candidates (tree, tree, const VEC(
 			    tree, tree, int, struct z_candidate **);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
 static bool magic_varargs_p (tree);
-static tree build_temp (tree, tree, int, diagnostic_t *);
+static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
 
 /* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
    NAME can take many forms...  */
@@ -4851,7 +4851,7 @@  enforce_access (tree basetype_path, tree decl, tre
 
 static tree
 build_temp (tree expr, tree type, int flags,
-	    diagnostic_t *diagnostic_kind)
+	    diagnostic_t *diagnostic_kind, tsubst_flags_t complain)
 {
   int savew, savee;
   VEC(tree,gc) *args;
@@ -4859,7 +4859,7 @@  build_temp (tree expr, tree type, int flags,
   savew = warningcount, savee = errorcount;
   args = make_tree_vector_single (expr);
   expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
-				    &args, type, flags, tf_warning_or_error);
+				    &args, type, flags, complain);
   release_tree_vector (args);
   if (warningcount > savew)
     *diagnostic_kind = DK_WARNING;
@@ -5132,7 +5132,7 @@  convert_like_real (conversion *convs, tree expr, t
 	   conversion (i.e. the second step of copy-initialization), so
 	   don't allow any more.  */
 	flags |= LOOKUP_NO_CONVERSION;
-      expr = build_temp (expr, totype, flags, &diag_kind);
+      expr = build_temp (expr, totype, flags, &diag_kind, complain);
       if (diag_kind && fn)
 	{
 	  if ((complain & tf_error))