aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2003-03-17 10:45:29 -0500
committerJason Merrill <jason@gcc.gnu.org>2003-03-17 10:45:29 -0500
commit35e939ae1c46ee21ad069d23f77c5e359c7c8ad1 (patch)
tree5e415b4ac71c0adab0b0fb00508728fe2bc54f8f
parentf1b62339fa1f8b2021750ffe334adc3da73e8d02 (diff)
downloadgcc-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/ChangeLog6
-rw-r--r--gcc/cp/decl.c16
-rw-r--r--gcc/testsuite/g++.dg/opt/nrv6.C26
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;
+}