diff mbox

C++ PATCH for DR 1518 (explicit default ctor and copy-list-initialization)

Message ID 554975EF.7000401@redhat.com
State New
Headers show

Commit Message

Jason Merrill May 6, 2015, 2:01 a.m. UTC
I went to draft standardese for DR 1518 this week and realized that it 
had already been resolved by DR 1630, which clarified that 
default-initialization can call explicit default constructors even in 
the context of copy-list-initialization.  So this patch adjusts my 
earlier approximation to reflect that.

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

Patch

commit 733826123adfc74ffb07e423fb8cd9311c8d6a86
Author: Jason Merrill <jason@redhat.com>
Date:   Mon May 4 06:45:03 2015 -0500

    	DR 1518
    	DR 1630
    	PR c++/54835
    	PR c++/60417
    	* call.c (convert_like_real): Check value-initialization before
    	explicit.
    	* typeck2.c (process_init_constructor_record): Don't set
    	CONSTRUCTOR_IS_DIRECT_INIT.
    	(process_init_constructor_array): Likewise.
    	* init.c (build_vec_init): Likewise.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 7bdf236..b77f69a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6243,19 +6243,9 @@  convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	tree convfn = cand->fn;
 	unsigned i;
 
-	/* When converting from an init list we consider explicit
-	   constructors, but actually trying to call one is an error.  */
-	if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn)
-	    /* Unless this is for direct-list-initialization.  */
-	    && !DIRECT_LIST_INIT_P (expr))
-	  {
-	    if (!(complain & tf_error))
-	      return error_mark_node;
-	    error ("converting to %qT from initializer list would use "
-		   "explicit constructor %qD", totype, convfn);
-	  }
-
-	/* If we're initializing from {}, it's value-initialization.  */
+	/* If we're initializing from {}, it's value-initialization.  Note
+	   that under the resolution of core 1630, value-initialization can
+	   use explicit constructors.  */
 	if (BRACE_ENCLOSED_INITIALIZER_P (expr)
 	    && CONSTRUCTOR_NELTS (expr) == 0
 	    && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype))
@@ -6271,6 +6261,18 @@  convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	    return expr;
 	  }
 
+	/* When converting from an init list we consider explicit
+	   constructors, but actually trying to call one is an error.  */
+	if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn)
+	    /* Unless this is for direct-list-initialization.  */
+	    && !DIRECT_LIST_INIT_P (expr))
+	  {
+	    if (!(complain & tf_error))
+	      return error_mark_node;
+	    error ("converting to %qT from initializer list would use "
+		   "explicit constructor %qD", totype, convfn);
+	  }
+
 	expr = mark_rvalue_use (expr);
 
 	/* Set user_conv_p on the argument conversions, so rvalue/base
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index a4fc9ff..c41e30c 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3720,7 +3720,6 @@  build_vec_init (tree base, tree maxindex, tree init,
 	  if (cxx_dialect >= cxx11 && AGGREGATE_TYPE_P (type))
 	    {
 	      init = build_constructor (init_list_type_node, NULL);
-	      CONSTRUCTOR_IS_DIRECT_INIT (init) = true;
 	    }
 	  else
 	    {
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index c0df823..6e0c777 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1285,7 +1285,6 @@  process_init_constructor_array (tree type, tree init,
 	       we can't rely on the back end to do it for us, so make the
 	       initialization explicit by list-initializing from T{}.  */
 	    next = build_constructor (init_list_type_node, NULL);
-	    CONSTRUCTOR_IS_DIRECT_INIT (next) = true;
 	    next = massage_init_elt (TREE_TYPE (type), next, complain);
 	    if (initializer_zerop (next))
 	      /* The default zero-initialization is fine for us; don't
@@ -1396,9 +1395,6 @@  process_init_constructor_record (tree type, tree init,
 	     for us, so build up TARGET_EXPRs.  If the type in question is
 	     a class, just build one up; if it's an array, recurse.  */
 	  next = build_constructor (init_list_type_node, NULL);
-	  /* Call this direct-initialization pending DR 1518 resolution so
-	     that explicit default ctors don't break valid C++03 code.  */
-	  CONSTRUCTOR_IS_DIRECT_INIT (next) = true;
 	  next = massage_init_elt (TREE_TYPE (field), next, complain);
 
 	  /* Warn when some struct elements are implicitly initialized.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-dr1518.C b/gcc/testsuite/g++.dg/cpp0x/initlist-dr1518.C
new file mode 100644
index 0000000..9f8ee0b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-dr1518.C
@@ -0,0 +1,27 @@ 
+// DR 1518
+// { dg-do compile { target c++11 } }
+
+struct A {
+  explicit A() = default;
+};
+
+struct B : A {
+  explicit B() = default;
+};
+
+struct C {
+  explicit C();
+};
+
+struct D : A {
+  C c;
+  explicit D() = default;
+};
+
+template<typename T> void f() {
+  T t = {};
+}
+template<typename T> void g() {
+  void x(T t);
+  x({});
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist40.C b/gcc/testsuite/g++.dg/cpp0x/initlist40.C
index 6e6a11a..de2e19d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist40.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist40.C
@@ -8,6 +8,6 @@  struct A
 
 int main()
 {
-  A a1 = { };			// { dg-error "explicit" }
+  A a1 = { };
   A a2 = { 24 };		// { dg-error "explicit" }
 }