This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCHes for Core 1288 and c++/58812 (ICE with excess braces)


The first patch implements core DR 1288, which adjusts the list-initialization rules so that an initializer-list containing a single element of the same type as the target is treated as the initializer by itself.

The second patch expands the excess braces diagnostic to cover reference initialization as well as scalar, and thereby avoids an ICE when trying to convert them.

Tested x86_64-pc-linux-gnu. First patch applied to trunk, second to both trunk and 4.8.
commit 516bb653326cd0ec8eb17c17c358eb0f8ed17e79
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Jan 27 11:05:01 2014 -0500

    	Core DR 1288
    	* call.c (reference_binding): Only elide braces if the single
    	element is reference-related.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 2c77973..7d6e621 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1460,16 +1460,29 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
   if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
     {
       maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
+      /* DR 1288: Otherwise, if the initializer list has a single element
+	 of type E and ... [T's] referenced type is reference-related to E,
+	 the object or reference is initialized from that element... */
+      if (CONSTRUCTOR_NELTS (expr) == 1)
+	{
+	  tree elt = CONSTRUCTOR_ELT (expr, 0)->value;
+	  if (error_operand_p (elt))
+	    return NULL;
+	  tree etype = TREE_TYPE (elt);
+	  if (reference_related_p (to, etype))
+	    {
+	      expr = elt;
+	      from = etype;
+	      goto skip;
+	    }
+	}
+      /* Otherwise, if T is a reference type, a prvalue temporary of the
+	 type referenced by T is copy-list-initialized or
+	 direct-list-initialized, depending on the kind of initialization
+	 for the reference, and the reference is bound to that temporary. */
       conv = implicit_conversion (to, from, expr, c_cast_p,
 				  flags, complain);
-      if (!CLASS_TYPE_P (to)
-	  && CONSTRUCTOR_NELTS (expr) == 1)
-	{
-	  expr = CONSTRUCTOR_ELT (expr, 0)->value;
-	  if (error_operand_p (expr))
-	    return NULL;
-	  from = TREE_TYPE (expr);
-	}
+    skip:;
     }
 
   if (TREE_CODE (from) == REFERENCE_TYPE)
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist22.C b/gcc/testsuite/g++.dg/cpp0x/initlist22.C
index f913aeb..19aefd3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist22.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist22.C
@@ -1,4 +1,4 @@
-// Core issue 934
+// Core issue 934/1288
 // { dg-options "-std=c++11" }
 
 int i;
@@ -13,12 +13,12 @@ struct A { int i; } a;
 
 A& r5 { i };			// { dg-error "" } reference to temporary
 A&& r6 { i };			// OK, aggregate initialization of temporary
-A& r7 { a };			// { dg-error "" } invalid aggregate initializer for A
-A&& r8 { a };			// { dg-error "" } invalid aggregate initializer for A
+A& r7 { a };			// OK, direct-initialization
+A&& r8 { a };			// { dg-error "lvalue" } binding && to lvalue
 
 struct B { B(int); int i; } b(0);
 
 B& r9 { i };			// { dg-error "" } reference to temporary
 B&& r10 { i };			// OK, make temporary with B(int) constructor
-B& r11 { b };			// { dg-error "" } reference to temporary
-B&& r12 { b };			// OK, make temporary with copy constructor
+B& r11 { b };			// OK, direct-initialization
+B&& r12 { b };			// { dg-error "lvalue" } binding && to lvalue
commit f6d43f1f8f3c233f916025837d246aba9e78fa65
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Jan 27 11:16:14 2014 -0500

    	PR c++/58812
    	* call.c (convert_like_real): Give helpful error about excess braces
    	for ck_rvalue of scalar type.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 7d6e621..b72f2d4 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5879,9 +5879,11 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
       && convs->kind != ck_ambig
       && (convs->kind != ck_ref_bind
 	  || convs->user_conv_p)
-      && convs->kind != ck_rvalue
+      && (convs->kind != ck_rvalue
+	  || SCALAR_TYPE_P (totype))
       && convs->kind != ck_base)
     {
+      bool complained = false;
       conversion *t = convs;
 
       /* Give a helpful error if this is bad because of excess braces.  */
@@ -5889,7 +5891,13 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  && SCALAR_TYPE_P (totype)
 	  && CONSTRUCTOR_NELTS (expr) > 0
 	  && BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT (expr, 0)->value))
-	permerror (loc, "too many braces around initializer for %qT", totype);
+	{
+	  complained = permerror (loc, "too many braces around initializer "
+				  "for %qT", totype);
+	  while (BRACE_ENCLOSED_INITIALIZER_P (expr)
+		 && CONSTRUCTOR_NELTS (expr) == 1)
+	    expr = CONSTRUCTOR_ELT (expr, 0)->value;
+	}
 
       for (; t ; t = next_conversion (t))
 	{
@@ -5925,9 +5933,10 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  else if (t->kind == ck_identity)
 	    break;
 	}
-       if (permerror (loc, "invalid conversion from %qT to %qT",
-                    TREE_TYPE (expr), totype)
-	   && fn)
+      if (!complained)
+	complained = permerror (loc, "invalid conversion from %qT to %qT",
+				TREE_TYPE (expr), totype);
+      if (complained && fn)
 	inform (DECL_SOURCE_LOCATION (fn),
 		"initializing argument %P of %qD", argnum, fn);
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist76.C b/gcc/testsuite/g++.dg/cpp0x/initlist76.C
new file mode 100644
index 0000000..ac419dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist76.C
@@ -0,0 +1,5 @@
+// PR c++/58812
+// { dg-require-effective-target c++11 }
+
+int i;
+int&& j{{ i }};			// { dg-error "too many braces" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist77.C b/gcc/testsuite/g++.dg/cpp0x/initlist77.C
new file mode 100644
index 0000000..49b9079
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist77.C
@@ -0,0 +1,10 @@
+// PR c++/58651
+// { dg-require-effective-target c++11 }
+
+struct A
+{
+  int i;
+  A(int j) : i{{j}} {}		// { dg-error "too many braces" }
+};
+
+A a(0);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]