aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2010-09-30 22:21:28 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2010-09-30 22:21:28 +0200
commit45c13d4cec5c33c3971a42d673503e93c2fbb424 (patch)
tree86af552168cf72dd7edf9f4c4c6f9ecd2893d26c /gcc
parent03d79dc39456d034c9b789d520c4f6161b0ecde6 (diff)
downloadgcc-45c13d4cec5c33c3971a42d673503e93c2fbb424.zip
gcc-45c13d4cec5c33c3971a42d673503e93c2fbb424.tar.gz
gcc-45c13d4cec5c33c3971a42d673503e93c2fbb424.tar.bz2
re PR target/45843 (__builtin_va_arg overwrites into adjacent stack location)
PR target/45843 * config/i386/i386.c (ix86_gimplify_va_arg): Use INTVAL (XEXP (slot, 1)) as prev_size. * g++.dg/torture/pr45843.C: New test. From-SVN: r164766
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/i386/i386.c4
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr45843.C28
4 files changed, 42 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7795da1..b82c99d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2010-09-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/45843
+ * config/i386/i386.c (ix86_gimplify_va_arg): Use
+ INTVAL (XEXP (slot, 1)) as prev_size.
+
2010-09-30 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/45837
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index c36ad74..0998f31 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -7524,6 +7524,8 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
tree dest_addr, dest;
int cur_size = GET_MODE_SIZE (mode);
+ gcc_assert (prev_size <= INTVAL (XEXP (slot, 1)));
+ prev_size = INTVAL (XEXP (slot, 1));
if (prev_size + cur_size > size)
{
cur_size = size - prev_size;
@@ -7556,7 +7558,7 @@ ix86_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
dest_addr = fold_convert (daddr_type, addr);
dest_addr = fold_build2 (POINTER_PLUS_EXPR, daddr_type, dest_addr,
- size_int (INTVAL (XEXP (slot, 1))));
+ size_int (prev_size));
if (cur_size == GET_MODE_SIZE (mode))
{
src = build_va_arg_indirect_ref (src_addr);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 71f9784..e3ffb18 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-09-30 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/45843
+ * g++.dg/torture/pr45843.C: New test.
+
2010-09-30 Janus Weil <janus@gcc.gnu.org>
PR fortran/45828
diff --git a/gcc/testsuite/g++.dg/torture/pr45843.C b/gcc/testsuite/g++.dg/torture/pr45843.C
new file mode 100644
index 0000000..f77b8cb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr45843.C
@@ -0,0 +1,28 @@
+// PR target/45843
+// { dg-do run }
+
+#include <stdarg.h>
+
+extern "C" void abort ();
+struct S { struct T { } a[14]; char b; };
+struct S arg, s;
+
+void
+foo (int z, ...)
+{
+ char c;
+ va_list ap;
+ va_start (ap, z);
+ c = 'a';
+ arg = va_arg (ap, struct S);
+ if (c != 'a')
+ abort ();
+ va_end (ap);
+}
+
+int
+main ()
+{
+ foo (1, s);
+ return 0;
+}