aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-01-27 23:30:55 -0500
committerJason Merrill <jason@gcc.gnu.org>2014-01-27 23:30:55 -0500
commitf235ad118fed420d99d985b116a3c6a1d054d398 (patch)
tree6f8b29307f926663f67c12f91ddb6e52c933453e /gcc
parent30f6b7844aad824eb90adc0962a3663c73d5aa16 (diff)
downloadgcc-f235ad118fed420d99d985b116a3c6a1d054d398.zip
gcc-f235ad118fed420d99d985b116a3c6a1d054d398.tar.gz
gcc-f235ad118fed420d99d985b116a3c6a1d054d398.tar.bz2
Core DR 1288
Core DR 1288 * call.c (reference_binding): Only elide braces if the single element is reference-related. From-SVN: r207164
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/call.c27
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist22.C10
3 files changed, 29 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b5693f2..707032f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
2014-01-27 Jason Merrill <jason@redhat.com>
+ Core DR 1288
+ * call.c (reference_binding): Only elide braces if the single
+ element is reference-related.
+
PR c++/58814
* typeck.c (cp_build_modify_expr): Make the RHS an rvalue before
stabilizing.
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);
- conv = implicit_conversion (to, from, expr, c_cast_p,
- flags, complain);
- if (!CLASS_TYPE_P (to)
- && CONSTRUCTOR_NELTS (expr) == 1)
+ /* 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)
{
- expr = CONSTRUCTOR_ELT (expr, 0)->value;
- if (error_operand_p (expr))
+ tree elt = CONSTRUCTOR_ELT (expr, 0)->value;
+ if (error_operand_p (elt))
return NULL;
- from = TREE_TYPE (expr);
+ 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);
+ 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