| Submitter | Ollie Wild |
|---|---|
| Date | Aug. 13, 2012, 8:47 p.m. |
| Message ID | <CAFOgFcRdX=8p2ctHZmAP=r6qZMWq4j1egtuFesawhOzbLPzU3Q@mail.gmail.com> |
| Download | mbox | patch |
| Permalink | /patch/177103/ |
| State | New |
| Headers | show |
Comments
On Mon, Aug 13, 2012 at 03:47:43PM -0500, Ollie Wild wrote: > diff --git a/gcc/cp/call.c b/gcc/cp/call.c > index 5345f2b..b2fac16 100644 > --- a/gcc/cp/call.c > +++ b/gcc/cp/call.c > @@ -8924,6 +8924,12 @@ extend_ref_init_temps_1 (tree decl, tree init, VEC(tree,gc) **cleanups) > tree sub = init; > tree *p; > STRIP_NOPS (sub); > + if (TREE_CODE (sub) == COMPOUND_EXPR) > + { > + TREE_OPERAND(sub, 1) = extend_ref_init_temps_1 ( > + decl, TREE_OPERAND(sub, 1), cleanups); > + return init; > + } The formatting doesn't match GCC coding conventions in several ways. You don't have spaces before (, and ( shouldn't be at the end of line if possible. TREE_OPERAND (sub, 1) = extend_ref_init_temps_1 (decl, TREE_OPERAND (sub, 1), cleanups); is what should be used instead. Jakub
Patch
diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 5345f2b..b2fac16 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -8924,6 +8924,12 @@ extend_ref_init_temps_1 (tree decl, tree init, VEC(tree,gc) **cleanups) tree sub = init; tree *p; STRIP_NOPS (sub); + if (TREE_CODE (sub) == COMPOUND_EXPR) + { + TREE_OPERAND(sub, 1) = extend_ref_init_temps_1 ( + decl, TREE_OPERAND(sub, 1), cleanups); + return init; + } if (TREE_CODE (sub) != ADDR_EXPR) return init; /* Deal with binding to a subobject. */ diff --git a/gcc/testsuite/g++.dg/init/lifetime3.C b/gcc/testsuite/g++.dg/init/lifetime3.C new file mode 100644 index 0000000..d099699 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/lifetime3.C @@ -0,0 +1,37 @@ +// PR c++/26714 +// { dg-do run } + +extern "C" void abort(); + +bool ok = false; +struct A { + A() { } + ~A() { if (!ok) abort(); } +}; + +struct B { + static A foo() { return A(); } +}; + +B b_g; + +struct scoped_ptr { + B* operator->() const { return &b_g; } + B* get() const { return &b_g; } +}; + +B *get() { return &b_g; } + +int main() +{ + scoped_ptr f; + const A& ref1 = f->foo(); + const A& ref2 = f.get()->foo(); + const A& ref3 = get()->foo(); + const A& ref4 = B::foo(); + B *pf = f.get(); + const A& ref5 = pf->foo(); + + + ok = true; +}
This patch fixes http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54197. Certain constructs (see bug for examples) cause C++ references to be initialized with COMPOUND_EXPR's. The old logic was ignoring these, causing those temporaries to be prematurely destroyed. Tested on trunk via full x86_64 bootstrap and testsuite. Okay for trunk and backport to gcc-4_7-branch? Ollie 2012-08-13 Ollie Wild <aaw@google.com> PR c++/54197 * gcc/cp/call.c (extend_ref_init_temps_1): Handle COMPOUND_EXPR trees. * gcc/testsuite/g++.dg/init/lifetime3.C: New test. commit dfd33145e3b32963e03b47bcc89f3eb2912714a6 Author: Ollie Wild <aaw@google.com> Date: Mon Aug 13 15:36:24 2012 -0500 2012-08-13 Ollie Wild <aaw@google.com> PR c++/54197 * gcc/cp/call.c (extend_ref_init_temps_1): Handle COMPOUND_EXPR trees. * gcc/testsuite/g++.dg/init/lifetime3.C: New test.