aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-08-15 14:08:42 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2007-08-15 14:08:42 +0200
commit59fe92745a5360e7771f9ca0b86301ff6ddb2ac1 (patch)
treedaf776af0f24665a9da545d0d072b17b91ce13ed
parent9bf5a5e86cc0d361ab73e0386b44adc7c7d00db5 (diff)
downloadgcc-59fe92745a5360e7771f9ca0b86301ff6ddb2ac1.zip
gcc-59fe92745a5360e7771f9ca0b86301ff6ddb2ac1.tar.gz
gcc-59fe92745a5360e7771f9ca0b86301ff6ddb2ac1.tar.bz2
re PR c++/32992 (Incorrect code generated for anonymous union and return)
PR c++/32992 * typeck.c (check_return_expr): Don't NRV optimize vars in anonymous unions. * decl.c (finish_function): Comment fix. * g++.dg/opt/nrv14.C: New test. From-SVN: r127510
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl.c2
-rw-r--r--gcc/cp/typeck.c1
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/opt/nrv14.C39
5 files changed, 53 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 892e8a6..6a7a4a4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2007-08-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/32992
+ * typeck.c (check_return_expr): Don't NRV optimize vars in
+ anonymous unions.
+ * decl.c (finish_function): Comment fix.
+
2007-08-15 Paolo Carlini <pcarlini@suse.de>
PR c++/33035
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9a9436a..b04fda3 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11569,7 +11569,7 @@ finish_function (int flags)
gcc_assert (stmts_are_full_exprs_p ());
/* Set up the named return value optimization, if we can. Candidate
- variables are selected in check_return_value. */
+ variables are selected in check_return_expr. */
if (current_function_return_value)
{
tree r = current_function_return_value;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d2e095c..a79f6e2 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6703,6 +6703,7 @@ check_return_expr (tree retval, bool *no_warning)
&& TREE_CODE (retval) == VAR_DECL
&& DECL_CONTEXT (retval) == current_function_decl
&& ! TREE_STATIC (retval)
+ && ! DECL_ANON_UNION_VAR_P (retval)
&& (DECL_ALIGN (retval)
>= DECL_ALIGN (DECL_RESULT (current_function_decl)))
/* The cv-unqualified type of the returned value must be the
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index eef5e69..45fc15c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2007-08-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/32992
+ * g++.dg/opt/nrv14.C: New test.
+
2007-08-15 Paolo Carlini <pcarlini@suse.de>
PR c++/33035
diff --git a/gcc/testsuite/g++.dg/opt/nrv14.C b/gcc/testsuite/g++.dg/opt/nrv14.C
new file mode 100644
index 0000000..22526d6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/nrv14.C
@@ -0,0 +1,39 @@
+// PR c++/32992
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort (void);
+
+struct A
+{
+ long int a1;
+ long int a2;
+ long int a3;
+};
+
+struct B
+{
+ long int f[3];
+ operator A ()
+ {
+ union
+ {
+ long int t[3];
+ A a;
+ };
+ for (int i = 0; i < 3; i++)
+ t[i] = f[i];
+ return a;
+ }
+};
+
+int
+main ()
+{
+ B b = { {1, 3, 5} };
+ A a = b;
+
+ if (a.a1 != b.f[0] || a.a2 != b.f[1] || a.a3 != b.f[2])
+ abort ();
+ return 0;
+}