diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/gimplify.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/nrv10.C | 48 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/nrv11.C | 58 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/temp1.C | 2 |
5 files changed, 120 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 331a5ab..ffa7c5f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2006-02-03 Jason Merrill <jason@redhat.com> + + PR c++/25979 + * gimplify.c (gimplify_modify_expr_rhs): Disable *& optimization for now. + + PR middle-end/25977 + * gimplify.c (gimplify_modify_expr_rhs): It's not always safe to do RVO + on the return slot if it's an NRV. + 2006-02-03 Zdenek Dvorak <dvorakz@suse.cz> * tree-ssa-loop-ivopts.c (enum use_type): Remove USE_OUTER. diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 8761609..f64b1cb 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -3190,6 +3190,7 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, while (ret != GS_UNHANDLED) switch (TREE_CODE (*from_p)) { +#if 0 case INDIRECT_REF: { /* If we have code like @@ -3211,6 +3212,7 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, ret = GS_UNHANDLED; break; } +#endif case TARGET_EXPR: { @@ -3272,8 +3274,9 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, bool use_target; if (TREE_CODE (*to_p) == RESULT_DECL + && DECL_NAME (*to_p) == NULL_TREE && needs_to_live_in_memory (*to_p)) - /* It's always OK to use the return slot directly. */ + /* It's OK to use the return slot directly unless it's an NRV. */ use_target = true; else if (!is_gimple_non_addressable (*to_p)) /* Don't use the original target if it's already addressable; diff --git a/gcc/testsuite/g++.dg/opt/nrv10.C b/gcc/testsuite/g++.dg/opt/nrv10.C new file mode 100644 index 0000000..d4cb92c --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/nrv10.C @@ -0,0 +1,48 @@ +// PR c++/25979 +// Bug: we were eliding too many temporaries, so that a1 was used +// as both 'a' and 'x' in the second operator+. +// { dg-do run } + +struct A +{ + A() : data1_(0), data2_(0) {} + A(int i, int j) : data1_(i), data2_(j) {} + A operator+(int); + friend A operator+(int, const A&); + ~A() {} +//private: + int data1_; + int data2_; +}; + +extern bool x; + +extern "C" void abort (); + +int main() +{ + A a1(1,2); + a1 = (x ? a1 + 3 : 3 + a1); + if (a1.data1_ != 3 || a1.data2_ != 2) + abort (); +} + +bool x = false; + +A +A::operator+(int i) +{ + A a; + a = *this; + a.data2_ = i; + return a; +} + +A +operator+(int i, const A& x) +{ + A a; + a = x; + a.data1_ = i; + return a; +} diff --git a/gcc/testsuite/g++.dg/opt/nrv11.C b/gcc/testsuite/g++.dg/opt/nrv11.C new file mode 100644 index 0000000..2b72f79 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/nrv11.C @@ -0,0 +1,58 @@ +// PR middle-end/25977 +// Bug: We were assuming that the return slot of the current function is +// always safe to use as the return slot for another call, because its +// address cannot escape. But its address can escape if we perform the +// named return value optimization. + +// { dg-do run } + +struct A +{ + A( int left, int top, int width, int height ) + : x1(left), y1(top), x2(left+width-1), y2(top+height-1) {} + + //A(const A& o) : x1(o.x1), y1(o.y1), x2(o.x2), y2(o.y2) {} + //A& operator=(const A& o ) { x1=o.x1; y1=o.y1; x2=o.x2; y2=o.y2; return *this; } + + A operator&(const A &r) const + { + A tmp(0, 0, -1, -1); + tmp.x1 = ((r.x1) < (x1) ? (x1) : (r.x1)); + tmp.x2 = ((x2) < (r.x2) ? (x2) : (r.x2)); + tmp.y1 = ((r.y1) < (y1) ? (y1) : (r.y1)); + tmp.y2 = ((y2) < (r.y2) ? (y2) : (r.y2)); + return tmp; + } + + int x1; + int y1; + int x2; + int y2; +}; + +bool operator==( const A &r1, const A &r2 ) +{ + return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2; +} + +static A test() +{ + A all = A( 0, 0, 1024, 768); + A a = all; + A r = all; + a = a & r; + return a; +} + +extern "C" void abort(void); + +int main( int argc, char ** argv ) +{ + A all = A( 0, 0, 1024, 768); + A a = test(); + + if ( ! ( a == all)) + abort(); + + return 0; +} diff --git a/gcc/testsuite/g++.dg/opt/temp1.C b/gcc/testsuite/g++.dg/opt/temp1.C index b822dc4..6b0e2f3 100644 --- a/gcc/testsuite/g++.dg/opt/temp1.C +++ b/gcc/testsuite/g++.dg/opt/temp1.C @@ -1,6 +1,6 @@ // PR c++/16405 // { dg-options "-O2" } -// { dg-do run } +// { dg-do run { xfail *-*-* } } // There should be exactly one temporary generated for the code in "f" // below when optimizing -- for the result of "b + c". We have no |