diff options
author | Jason Merrill <jason@redhat.com> | 2003-03-17 10:45:29 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2003-03-17 10:45:29 -0500 |
commit | 35e939ae1c46ee21ad069d23f77c5e359c7c8ad1 (patch) | |
tree | 5e415b4ac71c0adab0b0fb00508728fe2bc54f8f | |
parent | f1b62339fa1f8b2021750ffe334adc3da73e8d02 (diff) | |
download | gcc-35e939ae1c46ee21ad069d23f77c5e359c7c8ad1.zip gcc-35e939ae1c46ee21ad069d23f77c5e359c7c8ad1.tar.gz gcc-35e939ae1c46ee21ad069d23f77c5e359c7c8ad1.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/decl.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/nrv6.C | 26 |
3 files changed, 45 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c0a968f..2439edd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2003-03-16 Jason Merrill <jason@redhat.com> + + PR c++/9993 + * decl.c (finish_function): Only allow the NRVO to use variables + declared at function scope. + 2003-03-17 Andreas Jaeger <aj@suse.de> * Make-lang.in (cp/TAGS): Remove. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6d68251..e00a5f3 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 0000000..57ff12e --- /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; +} |