aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
+}