{
unsigned int this_alignment;
unsigned int lhs, rhs;
- unsigned int type_alignment;
-
- /* For pointer expressions, we know that the designated object is always at
- least as strictly aligned as the designated subtype, so we account for
- both type and expression information in this case.
-
- Beware that we can still get a dummy designated subtype here (e.g. Taft
- Amendment types), in which the alignment information is meaningless and
- should be ignored.
-
- We always compute a type_alignment value and return the MAX of it
- compared with what we get from the expression tree. Just set the
- type_alignment value to 0 when the type information is to be ignored. */
- type_alignment
- = ((POINTER_TYPE_P (TREE_TYPE (exp))
- && !TYPE_IS_DUMMY_P (TREE_TYPE (TREE_TYPE (exp))))
- ? TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))) : 0);
switch (TREE_CODE (exp))
{
break;
case PLUS_EXPR:
- case POINTER_PLUS_EXPR:
case MINUS_EXPR:
/* If two address are added, the alignment of the result is the
minimum of the two alignments. */
this_alignment = MIN (lhs, rhs);
break;
+ case POINTER_PLUS_EXPR:
+ lhs = known_alignment (TREE_OPERAND (exp, 0));
+ rhs = known_alignment (TREE_OPERAND (exp, 1));
+ /* If we don't know the alignment of the offset, we assume that
+ of the base. */
+ if (rhs == 0)
+ this_alignment = lhs;
+ else
+ this_alignment = MIN (lhs, rhs);
+ break;
+
case COND_EXPR:
/* If there is a choice between two values, use the smallest one. */
lhs = known_alignment (TREE_OPERAND (exp, 1));
break;
case INTEGER_CST:
- /* The first part of this represents the lowest bit in the constant,
- but is it in bytes, not bits. */
- this_alignment
- = MIN (BITS_PER_UNIT
- * (TREE_INT_CST_LOW (exp) & - TREE_INT_CST_LOW (exp)),
- BIGGEST_ALIGNMENT);
+ {
+ unsigned HOST_WIDE_INT c = TREE_INT_CST_LOW (exp);
+ /* The first part of this represents the lowest bit in the constant,
+ but it is originally in bytes, not bits. */
+ this_alignment = MIN (BITS_PER_UNIT * (c & -c), BIGGEST_ALIGNMENT);
+ }
break;
case MULT_EXPR:
lhs = known_alignment (TREE_OPERAND (exp, 0));
rhs = known_alignment (TREE_OPERAND (exp, 1));
- if (lhs == 0 || rhs == 0)
- this_alignment = MIN (BIGGEST_ALIGNMENT, MAX (lhs, rhs));
+ if (lhs == 0)
+ this_alignment = rhs;
+ else if (rhs == 0)
+ this_alignment = lhs;
else
- this_alignment = MIN (BIGGEST_ALIGNMENT, lhs * rhs);
+ this_alignment = MIN (lhs * rhs, BIGGEST_ALIGNMENT);
break;
case BIT_AND_EXPR:
break;
default:
- this_alignment = 0;
+ /* For other pointer expressions, we assume that the pointed-to object
+ is at least as aligned as the pointed-to type. Beware that we can
+ have a dummy type here (e.g. a Taft Amendment type), for which the
+ alignment is meaningless and should be ignored. */
+ if (POINTER_TYPE_P (TREE_TYPE (exp))
+ && !TYPE_IS_DUMMY_P (TREE_TYPE (TREE_TYPE (exp))))
+ this_alignment = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
+ else
+ this_alignment = 0;
break;
}
- return MAX (type_alignment, this_alignment);
+ return this_alignment;
}
\f
/* We have a comparison or assignment operation on two types, T1 and T2, which
--- /dev/null
+-- { dg-do compile }
+
+with System;
+with Unchecked_Conversion;
+
+procedure Warn5 is
+
+ type Digit_Type is range 0..15;
+
+ type Frequency_Type is array( 1..12) of Digit_Type;
+ pragma Pack(Frequency_Type);
+
+ type Element_Type is record
+ F : Frequency_Type;
+ end record;
+
+ type Array_Type is array (Natural range <>) of Element_Type;
+
+ type List_Type is record
+ A : Array_Type (0..1);
+ end record;
+ for List_Type'Alignment use 4;
+
+ type Pointer_Type is access Element_Type;
+ function To_Ptr is new Unchecked_Conversion(System.Address, Pointer_Type);
+
+ function Pointer (Pos : Natural; List : List_Type) return Pointer_Type is
+ begin
+ return To_Ptr(List.A(Pos)'Address); -- { dg-warning "source alignment" "" { target alpha*-*-* hppa*-*-* ia64-*-* mips*-*-* sparc*-*-* } }
+ end;
+
+begin
+ null;
+end;