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 to fix ref binding to array temporaries


In discussion of core issue 1232 we realized that we already do allow array temporaries in some cases (primarily as subobjects of class temporaries), so we ought to handle them consistently.

The first patch fixes direct binding to array prvalues, which has been specified for a while.

The second patch specifies the semantics of a conversion from initializer-list to array for binding the temporary to a reference.

Tested x86_64-pc-linux-gnu, applying to trunk and 4.6.
commit 43d838d444e21ec34ed9d72e2e64315129d02291
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Mar 24 14:48:44 2011 +0100

    	* call.c (reference_binding): Allow direct binding to an array
    	rvalue.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 93383c6..9a9ac76 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1429,7 +1429,9 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
 	  || (((CP_TYPE_CONST_NON_VOLATILE_P (to)
 		&& !(flags & LOOKUP_NO_TEMP_BIND))
 	       || TYPE_REF_IS_RVALUE (rto))
-	      && (CLASS_TYPE_P (from) || (expr && lvalue_p (expr))))))
+	      && (CLASS_TYPE_P (from)
+		  || TREE_CODE (from) == ARRAY_TYPE
+		  || (expr && lvalue_p (expr))))))
     {
       /* [dcl.init.ref]
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C b/gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C
new file mode 100644
index 0000000..25113d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C
@@ -0,0 +1,5 @@
+// { dg-options -std=c++0x }
+
+typedef int IRT[2];
+
+const IRT& ir = IRT{1,2};
commit e84d467f48170f6b8fda35b38569cdab4104427f
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Mar 24 15:36:12 2011 +0100

    	Core 1232
    	* call.c (build_array_conv): New.
    	(implicit_conversion): Use it.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 9a9ac76..a1cfa96 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -801,6 +801,53 @@ build_aggr_conv (tree type, tree ctor, int flags)
   return c;
 }
 
+/* Represent a conversion from CTOR, a braced-init-list, to TYPE, an
+   array type, if such a conversion is possible.  */
+
+static conversion *
+build_array_conv (tree type, tree ctor, int flags)
+{
+  conversion *c;
+  unsigned HOST_WIDE_INT len = CONSTRUCTOR_NELTS (ctor);
+  tree elttype = TREE_TYPE (type);
+  unsigned i;
+  tree val;
+  bool bad = false;
+  bool user = false;
+  enum conversion_rank rank = cr_exact;
+
+  if (TYPE_DOMAIN (type))
+    {
+      unsigned HOST_WIDE_INT alen = tree_low_cst (array_type_nelts_top (type), 1);
+      if (alen < len)
+	return NULL;
+    }
+
+  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), i, val)
+    {
+      conversion *sub
+	= implicit_conversion (elttype, TREE_TYPE (val), val,
+			       false, flags);
+      if (sub == NULL)
+	return NULL;
+
+      if (sub->rank > rank)
+	rank = sub->rank;
+      if (sub->user_conv_p)
+	user = true;
+      if (sub->bad_p)
+	bad = true;
+    }
+
+  c = alloc_conversion (ck_aggr);
+  c->type = type;
+  c->rank = rank;
+  c->user_conv_p = user;
+  c->bad_p = bad;
+  c->u.next = NULL;
+  return c;
+}
+
 /* Build a representation of the identity conversion from EXPR to
    itself.  The TYPE should match the type of EXPR, if EXPR is non-NULL.  */
 
@@ -1623,6 +1670,8 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
 	      return conv;
 	    }
 	}
+      else if (TREE_CODE (to) == ARRAY_TYPE)
+	return build_array_conv (to, expr, flags);
     }
 
   if (expr != NULL_TREE
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-array2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-array2.C
new file mode 100644
index 0000000..19eec33
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-array2.C
@@ -0,0 +1,12 @@
+// { dg-options -std=c++0x }
+
+typedef int IA[2];
+typedef double DA[2];
+
+void f(const IA&) { }
+void f(const DA&);
+
+int main()
+{
+  f({1,2});
+}

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