Patchwork C++ PATCH to implement conditional conversions (n3323)

login
register
mail settings
Submitter Jason Merrill
Date April 22, 2013, 7:24 p.m.
Message ID <51758E8A.6010003@redhat.com>
Download mbox | patch
Permalink /patch/238654/
State New
Headers show

Comments

Jason Merrill - April 22, 2013, 7:24 p.m.
This paper corrected a defect in the language whereby we were 
prematurely rejecting as ambiguous a conversion required by a context, 
such as a delete-expression that wants some pointer type, when the class 
has multiple conversion operators to similar types.  In many cases, we 
can resolve that using normal overload resolution; the only time we need 
to give up is when the conversion operators convert to different types.

This paper was accepted after C++11, but it seems like a defect fix to 
me, so I'm not limiting it to C++1y mode.

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

Patch

commit 7e137f36fd739df81bc59fee16cc5548d3cb6207
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Apr 22 14:03:58 2013 -0400

    	N3323
    
    	* cvt.c (build_expr_type_conversion): Two conversions that return
    	the same type aren't necessarily ambiguous.

diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index a3b7358..93be76a 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1630,17 +1630,24 @@  build_expr_type_conversion (int desires, tree expr, bool complain)
 	{
 	  if (winner)
 	    {
-	      if (complain)
+	      tree winner_type
+		= non_reference (TREE_TYPE (TREE_TYPE (winner)));
+
+	      if (!same_type_ignoring_top_level_qualifiers_p (winner_type,
+							      candidate))
 		{
-		  error ("ambiguous default type conversion from %qT",
-			 basetype);
-		  error ("  candidate conversions include %qD and %qD",
-			 winner, cand);
+		  if (complain)
+		    {
+		      error ("ambiguous default type conversion from %qT",
+			     basetype);
+		      error ("  candidate conversions include %qD and %qD",
+			     winner, cand);
+		    }
+		  return error_mark_node;
 		}
-	      return error_mark_node;
 	    }
-	  else
-	    winner = cand;
+
+	  winner = cand;
 	}
     }
 
diff --git a/gcc/testsuite/g++.dg/cpp1y/context-conv1.C b/gcc/testsuite/g++.dg/cpp1y/context-conv1.C
new file mode 100644
index 0000000..fe20cab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/context-conv1.C
@@ -0,0 +1,32 @@ 
+// N3323
+
+#define assert(E) if(!(E))__builtin_abort();
+
+template<class T>
+class zero_init
+{
+public:
+  zero_init( )
+    : val( static_cast<T>(0) ) { }
+  zero_init( T val ) : val( val )
+  { }
+  operator T & ( ) { return val; }
+  operator T ( ) const { return val; }
+private:
+  T val;
+};
+
+void f()
+{
+  zero_init<int*> p; assert( p == 0 );
+  p = new int(7);
+  assert( *p == 7 );
+  delete p; // error!
+
+  zero_init<int> i; assert( i == 0 );
+  i = 7;
+  assert( i == 7 );
+  switch( i ) {  } // error!
+
+  int *vp = new int[i];
+}