From 35e939ae1c46ee21ad069d23f77c5e359c7c8ad1 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 17 Mar 2003 10:45:29 -0500 Subject: [PATCH] re PR c++/9993 (destructor not called for local object created within and returned from infinite loop) PR c++/9993 * decl.c (finish_function): Only allow the NRVO to use variables declared at function scope. From-SVN: r64488 --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/decl.c | 16 +++++++++++++--- gcc/testsuite/g++.dg/opt/nrv6.C | 26 ++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/nrv6.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c0a968f33d0..2439eddb630 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2003-03-16 Jason Merrill + + PR c++/9993 + * decl.c (finish_function): Only allow the NRVO to use variables + declared at function scope. + 2003-03-17 Andreas Jaeger * Make-lang.in (cp/TAGS): Remove. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6d682510630..e00a5f32e38 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -14092,11 +14092,21 @@ finish_function (int flags) if (current_function_return_value) { tree r = current_function_return_value; - /* This is only worth doing for fns that return in memory--and - simpler, since we don't have to worry about promoted modes. */ + tree outer; + if (r != error_mark_node - && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)))) + /* This is only worth doing for fns that return in memory--and + simpler, since we don't have to worry about promoted modes. */ + && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))) + /* Only allow this for variables declared in the outer scope of + the function so we know that their lifetime always ends with a + return; see g++.dg/opt/nrv6.C. We could be more flexible if + we were to do this optimization in tree-ssa. */ + /* Skip the artificial function body block. */ + && (outer = BLOCK_SUBBLOCKS (BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl))), + chain_member (r, BLOCK_VARS (outer)))) { + DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fndecl)); walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl), nullify_returns_r, r); diff --git a/gcc/testsuite/g++.dg/opt/nrv6.C b/gcc/testsuite/g++.dg/opt/nrv6.C new file mode 100644 index 00000000000..57ff12e41f4 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/nrv6.C @@ -0,0 +1,26 @@ +// PR c++/9993 +// Bug: We were failing to destroy b. + +// { dg-do run } + +int c, d; + +struct Object { + Object() { ++c; } + Object(const Object&) { ++c; } + ~Object() { ++d; } +}; + +Object function() { + int i = 0; + do { + Object b; + if (i++ == 2) + return b; + } while (1); +} + +int main() { + function(); + return c != d; +} -- 2.30.2