From: Jason Merrill Date: Fri, 9 May 2014 18:16:18 +0000 (-0400) Subject: DR 587 PR c++/51317 X-Git-Tag: releases/gcc-5.1.0~7664 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e8ee694a14382f4b2cea7ec5622e2be5329d581d;p=thirdparty%2Fgcc.git DR 587 PR c++/51317 DR 587 PR c++/51317 * call.c (build_conditional_expr_1, conditional_conversion): Handle non-class lvalues and xvalues that differ only in cv-qualifiers. From-SVN: r210285 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ab3a3f4357d6..228fe959822f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2014-05-09 Jason Merrill + DR 587 + PR c++/51317 + * call.c (build_conditional_expr_1, conditional_conversion): Handle + non-class lvalues and xvalues that differ only in cv-qualifiers. + DR 5 PR c++/60019 * call.c (build_user_type_conversion_1): The copy-init temporary diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 187fc776e46d..9e83c4a8b73a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4382,20 +4382,31 @@ conditional_conversion (tree e1, tree e2, tsubst_flags_t complain) If E2 is an lvalue: E1 can be converted to match E2 if E1 can be implicitly converted (clause _conv_) to the type "lvalue reference to T2", subject to the constraint that in the conversion the - reference must bind directly (_dcl.init.ref_) to an lvalue. */ - if (real_lvalue_p (e2)) + reference must bind directly (_dcl.init.ref_) to an lvalue. + + If E2 is an xvalue: E1 can be converted to match E2 if E1 can be + implicitly converted to the type "rvalue reference to T2", subject to + the constraint that the reference must bind directly. */ + if (lvalue_or_rvalue_with_address_p (e2)) { - conv = implicit_conversion (build_reference_type (t2), + tree rtype = cp_build_reference_type (t2, !real_lvalue_p (e2)); + conv = implicit_conversion (rtype, t1, e1, /*c_cast_p=*/false, LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND |LOOKUP_ONLYCONVERTING, complain); - if (conv) + if (conv && !conv->bad_p) return conv; } + /* If E2 is a prvalue or if neither of the conversions above can be done + and at least one of the operands has (possibly cv-qualified) class + type: */ + if (!CLASS_TYPE_P (t1) && !CLASS_TYPE_P (t2)) + return NULL; + /* [expr.cond] If E1 and E2 have class type, and the underlying class types are @@ -4690,10 +4701,17 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3, /* [expr.cond] Otherwise, if the second and third operand have different types, - and either has (possibly cv-qualified) class type, an attempt is - made to convert each of those operands to the type of the other. */ + and either has (possibly cv-qualified) class type, or if both are + glvalues of the same value category and the same type except for + cv-qualification, an attempt is made to convert each of those operands + to the type of the other. */ else if (!same_type_p (arg2_type, arg3_type) - && (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type))) + && (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type) + || (same_type_ignoring_top_level_qualifiers_p (arg2_type, + arg3_type) + && lvalue_or_rvalue_with_address_p (arg2) + && lvalue_or_rvalue_with_address_p (arg3) + && real_lvalue_p (arg2) == real_lvalue_p (arg3)))) { conversion *conv2; conversion *conv3; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cond2.C b/gcc/testsuite/g++.dg/cpp0x/rv-cond2.C new file mode 100644 index 000000000000..e231b11e1a6d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/rv-cond2.C @@ -0,0 +1,11 @@ +// { dg-do compile { target c++11 } } + +template struct ST; +template struct ST {}; + +int&& f(); +const int&& g(); + +void h(bool b) { + ST(); +} diff --git a/gcc/testsuite/g++.dg/expr/cond14.C b/gcc/testsuite/g++.dg/expr/cond14.C new file mode 100644 index 000000000000..527628794212 --- /dev/null +++ b/gcc/testsuite/g++.dg/expr/cond14.C @@ -0,0 +1,6 @@ +// DR 587 +// PR c++/51317 + +int x = 1; +int const y = 2; +int const *p = &(1 ? x : y); // error: lvalue required as unary '&' operand diff --git a/gcc/testsuite/g++.dg/warn/return-reference.C b/gcc/testsuite/g++.dg/warn/return-reference.C index 83021900dbd7..710e87c8cbdf 100644 --- a/gcc/testsuite/g++.dg/warn/return-reference.C +++ b/gcc/testsuite/g++.dg/warn/return-reference.C @@ -7,7 +7,7 @@ foo1() { static int empty; const int* x = bar(); - return (x ? *x : empty); // { dg-bogus ".*" "" { xfail *-*-* } } + return (x ? *x : empty); // { dg-bogus ".*" } } const int&