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
This commit is contained in:
Jason Merrill 2003-03-17 10:45:29 -05:00 committed by Jason Merrill
parent f1b62339fa
commit 35e939ae1c
3 changed files with 45 additions and 3 deletions

View file

@ -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.

View file

@ -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);

View file

@ -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;
}