From: Jason Merrill Date: Wed, 14 Dec 2011 16:03:37 +0000 (-0500) Subject: re PR c++/51406 ([c++0x] Incorrect result of static_cast to rvalue reference to base... X-Git-Tag: releases/gcc-4.5.4~322 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b6759185695312b8f1685b23a794f9068f6db74c;p=thirdparty%2Fgcc.git re PR c++/51406 ([c++0x] Incorrect result of static_cast to rvalue reference to base class.) PR c++/51406 PR c++/51161 * typeck.c (build_static_cast_1): Fix cast of lvalue to base rvalue reference. From-SVN: r182340 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c61269d97ee7..2f94d210c6da 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2011-12-13 Jason Merrill + + PR c++/51406 + PR c++/51161 + * typeck.c (build_static_cast_1): Fix cast of lvalue to + base rvalue reference. + 2011-10-19 Jason Merrill PR c++/50793 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 7cdcee939fe4..b67ab1f05061 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5674,8 +5674,18 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, && reference_related_p (TREE_TYPE (type), intype) && (c_cast_p || at_least_as_qualified_p (TREE_TYPE (type), intype))) { - expr = build_typed_address (expr, type); - return convert_from_reference (expr); + /* Handle the lvalue case here by casting to lvalue reference and + then changing it to an rvalue reference. Casting an xvalue to + rvalue reference will be handled by the main code path. */ + tree lref = cp_build_reference_type (TREE_TYPE (type), false); + result = (perform_direct_initialization_if_possible + (lref, expr, c_cast_p, complain)); + result = cp_fold_convert (type, result); + /* Make sure we don't fold back down to a named rvalue reference, + because that would be an lvalue. */ + if (DECL_P (result)) + result = build1 (NON_LVALUE_EXPR, type, result); + return convert_from_reference (result); } orig = expr; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 67602c3c967b..8319732b01ee 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-12-13 Jason Merrill + + PR c++/51406 + PR c++/51161 + * g++.dg/cpp0x/rv-cast3.C: New. + * g++.dg/cpp0x/rv-cast4.C: New. + 2011-12-09 Kazu Hirata Backport from mainline: diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast3.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast3.C new file mode 100644 index 000000000000..6c70324aa81e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/rv-cast3.C @@ -0,0 +1,17 @@ +// PR c++/51406 +// { dg-do run { target c++11 } } + +extern "C" int printf(const char *,...); +extern "C" void abort(); + +struct A { int a; A() : a(1) {} }; +struct B { int b; B() : b(2) {} }; +struct X : A, B {}; + +int main() { + X x; + int a=static_cast(x).a; + int b=static_cast(x).b; + // printf ("%d %d\n", a, b); + if (a!=1 || b!=2) abort(); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast4.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast4.C new file mode 100644 index 000000000000..13f369d6108f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/rv-cast4.C @@ -0,0 +1,13 @@ +// PR c++/51161 +// { dg-do compile { target c++11 } } + +struct A{}; +struct B : A{}; +struct C : A{}; +struct D : B, C{}; + +int main() +{ + D d; + static_cast(d); // { dg-error "ambiguous" } +}