summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/expr.c51
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/align-nest.c28
-rw-r--r--gcc/testsuite/gnat.dg/misaligned_nest.adb26
5 files changed, 111 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3d9a9b35ae6..2be0ee95914 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2009-05-28 Olivier Hainque <hainque@adacore.com>
+
+ * expr.c (target_align): New function. Alignment the TARGET of an
+ assignment may be assume to have.
+ (highest_pow2_factor_for_target): Use it instead of relying on
+ immediate tree attributes of TARGET, not necessarily honored when
+ intermediate bitfields are involved.
+
2009-05-27 H.J. Lu <hongjiu.lu@intel.com>
PR target/40266
diff --git a/gcc/expr.c b/gcc/expr.c
index fd27483d011..1ecdb0277d2 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6224,6 +6224,45 @@ component_ref_field_offset (tree exp)
else
return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
}
+
+/* Alignment in bits the TARGET of an assignment may be assumed to have. */
+
+static unsigned HOST_WIDE_INT
+target_align (const_tree target)
+{
+ /* We might have a chain of nested references with intermediate misaligning
+ bitfields components, so need to recurse to find out. */
+
+ unsigned HOST_WIDE_INT this_align, outer_align;
+
+ switch (TREE_CODE (target))
+ {
+ case BIT_FIELD_REF:
+ return 1;
+
+ case COMPONENT_REF:
+ this_align = DECL_ALIGN (TREE_OPERAND (target, 1));
+ outer_align = target_align (TREE_OPERAND (target, 0));
+ return MIN (this_align, outer_align);
+
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ this_align = TYPE_ALIGN (TREE_TYPE (target));
+ outer_align = target_align (TREE_OPERAND (target, 0));
+ return MIN (this_align, outer_align);
+
+ CASE_CONVERT:
+ case NON_LVALUE_EXPR:
+ case VIEW_CONVERT_EXPR:
+ this_align = TYPE_ALIGN (TREE_TYPE (target));
+ outer_align = target_align (TREE_OPERAND (target, 0));
+ return MAX (this_align, outer_align);
+
+ default:
+ return TYPE_ALIGN (TREE_TYPE (target));
+ }
+}
+
/* Given an rtx VALUE that may contain additions and multiplications, return
an equivalent value that just refers to a register, memory, or constant.
@@ -6670,14 +6709,10 @@ highest_pow2_factor (const_tree exp)
static unsigned HOST_WIDE_INT
highest_pow2_factor_for_target (const_tree target, const_tree exp)
{
- unsigned HOST_WIDE_INT target_align, factor;
-
- factor = highest_pow2_factor (exp);
- if (TREE_CODE (target) == COMPONENT_REF)
- target_align = DECL_ALIGN_UNIT (TREE_OPERAND (target, 1));
- else
- target_align = TYPE_ALIGN_UNIT (TREE_TYPE (target));
- return MAX (factor, target_align);
+ unsigned HOST_WIDE_INT talign = target_align (target) / BITS_PER_UNIT;
+ unsigned HOST_WIDE_INT factor = highest_pow2_factor (exp);
+
+ return MAX (factor, talign);
}
/* Return &VAR expression for emulated thread local VAR. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f54f138eeb6..0cc0a1000e4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2009-05-28 Olivier Hainque <hainque@adacore.com>
+ Eric Botcazou <botcazou@adacore.com>
+
+ * gcc.c-torture/execute/align-nest.c: New testcase.
+ * gnat.dg/misaligned_nest.adb: New testcase.
+
2009-05-27 Rafael Avila de Espindola <espindola@google.com>
* g++.dg/plugin/attribute_plugin.c: Include gcc-plugin.h first.
diff --git a/gcc/testsuite/gcc.c-torture/execute/align-nest.c b/gcc/testsuite/gcc.c-torture/execute/align-nest.c
new file mode 100644
index 00000000000..2ff2952c70c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/align-nest.c
@@ -0,0 +1,28 @@
+
+void foo(int n)
+{
+ typedef struct
+ {
+ int value;
+ } myint;
+
+ struct S
+ {
+ int i[n];
+ unsigned int b:1;
+ myint mi;
+ } __attribute__ ((packed)) __attribute__ ((aligned (4)));
+
+ struct S s[2];
+ int k;
+
+ for (k = 0; k < 2; k ++)
+ s[k].mi.value = 0;
+}
+
+int main ()
+{
+ foo (2);
+ return 0;
+}
+
diff --git a/gcc/testsuite/gnat.dg/misaligned_nest.adb b/gcc/testsuite/gnat.dg/misaligned_nest.adb
new file mode 100644
index 00000000000..3b6fd845da4
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/misaligned_nest.adb
@@ -0,0 +1,26 @@
+-- { dg-do run }
+-- { dg-options "-gnatp" }
+
+procedure Misaligned_Nest is
+
+ type Int is record
+ V : Integer;
+ end record;
+
+ type Block is record
+ B : Boolean;
+ I : Int;
+ end record;
+ pragma Pack (Block);
+ for Block'Alignment use 1;
+
+ type Pair is array (1 .. 2) of Block;
+
+ P : Pair;
+begin
+ for K in P'Range loop
+ P(K).I.V := 1;
+ end loop;
+end;
+
+