aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2009-08-20 00:51:20 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2009-08-20 00:51:20 +0200
commitb8e444f4381296174b6098aad12de229bfb1f887 (patch)
treee967345a26c84656cfebfc8e15d937bdfd7e968a /gcc
parent0115d4a36f4ec51a9d70efe91d595b8a002facd2 (diff)
downloadgcc-b8e444f4381296174b6098aad12de229bfb1f887.zip
gcc-b8e444f4381296174b6098aad12de229bfb1f887.tar.gz
gcc-b8e444f4381296174b6098aad12de229bfb1f887.tar.bz2
re PR middle-end/41123 (ICE in expand_expr_real_1)
PR middle-end/41123 * expr.c (expand_expr_real_1) <normal_inner_ref>: Handle all kinds of CONCAT, not just bitpos 0 bitsize size of the whole CONCAT. * gcc.dg/pr41123.c: New test. From-SVN: r150946
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/expr.c37
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/pr41123.c46
4 files changed, 84 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 76f6060..3a6e261 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2009-08-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/41123
+ * expr.c (expand_expr_real_1) <normal_inner_ref>: Handle all kinds
+ of CONCAT, not just bitpos 0 bitsize size of the whole CONCAT.
+
2009-08-19 Jason Merrill <jason@redhat.com>
* doc/invoke.texi (C++ Dialect Options): Note change of minimum
diff --git a/gcc/expr.c b/gcc/expr.c
index 08c747e..6805cdc 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -7871,6 +7871,33 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|| mode1 == BLKmode
|| bitpos + bitsize > GET_MODE_BITSIZE (mode2));
+ /* Handle CONCAT first. */
+ if (GET_CODE (op0) == CONCAT && !must_force_mem)
+ {
+ if (bitpos == 0
+ && bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
+ return op0;
+ if (bitpos == 0
+ && bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
+ && bitsize)
+ {
+ op0 = XEXP (op0, 0);
+ mode2 = GET_MODE (op0);
+ }
+ else if (bitpos == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
+ && bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 1)))
+ && bitpos
+ && bitsize)
+ {
+ op0 = XEXP (op0, 1);
+ bitpos = 0;
+ mode2 = GET_MODE (op0);
+ }
+ else
+ /* Otherwise force into memory. */
+ must_force_mem = 1;
+ }
+
/* If this is a constant, put it in a register if it is a legitimate
constant and we don't need a memory reference. */
if (CONSTANT_P (op0)
@@ -7944,16 +7971,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
MEM_VOLATILE_P (op0) = 1;
}
- /* The following code doesn't handle CONCAT.
- Assume only bitpos == 0 can be used for CONCAT, due to
- one element arrays having the same mode as its element. */
- if (GET_CODE (op0) == CONCAT)
- {
- gcc_assert (bitpos == 0
- && bitsize == GET_MODE_BITSIZE (GET_MODE (op0)));
- return op0;
- }
-
/* In cases where an aligned union has an unaligned object
as a field, we might be extracting a BLKmode value from
an integer-mode (e.g., SImode) object. Handle this case
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a292949..993f2c3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-08-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/41123
+ * gcc.dg/pr41123.c: New test.
+
2009-08-19 Jason Merrill <jason@redhat.com>
PR c++/41120
diff --git a/gcc/testsuite/gcc.dg/pr41123.c b/gcc/testsuite/gcc.dg/pr41123.c
new file mode 100644
index 0000000..076edb4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr41123.c
@@ -0,0 +1,46 @@
+/* PR middle-end/41123 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-strict-aliasing" } */
+
+struct S { char a, b, c, d, e, f, g, h; };
+struct T { int a, b; };
+
+struct S
+f1 (float _Complex x)
+{
+ return *(struct S *) & x;
+}
+
+int
+f2 (float _Complex x)
+{
+ struct S f = f1 (x);
+ return f.b;
+}
+
+struct T
+f3 (float _Complex x)
+{
+ return *(struct T *) & x;
+}
+
+int
+f4 (float _Complex x)
+{
+ struct T f = f3 (x);
+ return f.a;
+}
+
+int
+f5 (float _Complex x)
+{
+ struct T f = f3 (x);
+ return f.b;
+}
+
+struct T
+f6 (float _Complex x)
+{
+ struct T f = f3 (x);
+ return f;
+}