This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Ada] Warn on suspiciously large alignments
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 7 Mar 2008 18:45:38 +0100
- Subject: [Ada] Warn on suspiciously large alignments
As suggested by Robert, this patch implements a warning for suspiciously
large alignments. The idea is to catch errors about the (alignment,byte)
vs (size,bit) discrepancy. It is triggered for types with large specified
alignments (greater than the maximum mode size) and alignment/size ratios
greater or equal to the byte/bit ratio. For example
type R is record
A, B, C, D : Character;
end record;
for R'Size use 32;
for R'Alignment use 32;
7. for R'Alignment use 32;
|
>>> warning: suspiciously large alignment specified for "R"
Tested on i586-suse-linux, applied on the mainline.
2008-03-07 Eric Botcazou <ebotcazou@adacore.com>
* decl.c (gnat_to_gnu_entity): Issue a warning on suspiciously
large alignments specified for types.
(validate_alignment): Minor cleanup.
2008-03-07 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/specs/alignment2.ads: New test.
--
Eric Botcazou
with Interfaces; use Interfaces;
package Alignment2 is
-- warning
type R1 is record
A, B, C, D : Integer_8;
end record;
for R1'Size use 32;
for R1'Alignment use 32; -- { dg-warning "suspiciously large alignment" }
-- warning
type R2 is record
A, B, C, D : Integer_8;
end record;
for R2'Alignment use 32; -- { dg-warning "suspiciously large alignment" }
-- OK, big size
type R3 is record
A, B, C, D : Integer_8;
end record;
for R3'Size use 32 * 8;
for R3'Alignment use 32;
-- OK, big size
type R4 is record
A, B, C, D, E, F, G, H : Integer_32;
end record;
for R4'Alignment use 32;
-- warning
type I1 is new Integer_32;
for I1'Size use 32;
for I1'Alignment use 32; -- { dg-warning "suspiciously large alignment" }
-- warning
type I2 is new Integer_32;
for I2'Alignment use 32; -- { dg-warning "suspiciously large alignment" }
-- OK, big size
type I3 is new Integer_32;
for I3'Size use 32 * 8;
for I3'Alignment use 32;
end Alignment2;
Index: decl.c
===================================================================
--- decl.c (revision 133011)
+++ decl.c (working copy)
@@ -4086,8 +4086,38 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
if (align != 0 || TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE)
;
else if (Known_Alignment (gnat_entity))
- align = validate_alignment (Alignment (gnat_entity), gnat_entity,
- TYPE_ALIGN (gnu_type));
+ {
+ align = validate_alignment (Alignment (gnat_entity), gnat_entity,
+ TYPE_ALIGN (gnu_type));
+
+ /* Warn on suspiciously large alignments. This should catch
+ errors about the (alignment,byte)/(size,bit) discrepancy. */
+ if (align > BIGGEST_ALIGNMENT && Has_Alignment_Clause (gnat_entity))
+ {
+ tree size;
+
+ /* If a size was specified, take it into account. Otherwise
+ use the RM size for records as the type size has already
+ been adjusted to the alignment. */
+ if (gnu_size)
+ size = gnu_size;
+ else if ((TREE_CODE (gnu_type) == RECORD_TYPE
+ || TREE_CODE (gnu_type) == UNION_TYPE
+ || TREE_CODE (gnu_type) == QUAL_UNION_TYPE)
+ && !TYPE_IS_FAT_POINTER_P (gnu_type))
+ size = rm_size (gnu_type);
+ else
+ size = TYPE_SIZE (gnu_type);
+
+ /* Consider an alignment as suspicious if the alignment/size
+ ratio is greater or equal to the byte/bit ratio. */
+ if (host_integerp (size, 1)
+ && align >= TREE_INT_CST_LOW (size) * BITS_PER_UNIT)
+ post_error_ne ("?suspiciously large alignment specified for&",
+ Expression (Alignment_Clause (gnat_entity)),
+ gnat_entity);
+ }
+ }
else if (Is_Atomic (gnat_entity) && !gnu_size
&& host_integerp (TYPE_SIZE (gnu_type), 1)
&& integer_pow2p (TYPE_SIZE (gnu_type)))
@@ -6904,25 +6934,25 @@ make_type_from_size (tree type, tree siz
static unsigned int
validate_alignment (Uint alignment, Entity_Id gnat_entity, unsigned int align)
{
- Node_Id gnat_error_node = gnat_entity;
- unsigned int new_align;
-
unsigned int max_allowed_alignment = get_target_maximum_allowed_alignment ();
-
- if (Present (Alignment_Clause (gnat_entity)))
- gnat_error_node = Expression (Alignment_Clause (gnat_entity));
+ unsigned int new_align;
+ Node_Id gnat_error_node;
/* Don't worry about checking alignment if alignment was not specified
by the source program and we already posted an error for this entity. */
-
if (Error_Posted (gnat_entity) && !Has_Alignment_Clause (gnat_entity))
return align;
+ /* Post the error on the alignment clause if any. */
+ if (Present (Alignment_Clause (gnat_entity)))
+ gnat_error_node = Expression (Alignment_Clause (gnat_entity));
+ else
+ gnat_error_node = gnat_entity;
+
/* Within GCC, an alignment is an integer, so we must make sure a value is
specified that fits in that range. Also, there is an upper bound to
alignments we can support/allow. */
-
- if (! UI_Is_In_Int_Range (alignment)
+ if (!UI_Is_In_Int_Range (alignment)
|| ((new_align = UI_To_Int (alignment)) > max_allowed_alignment))
post_error_ne_num ("largest supported alignment for& is ^",
gnat_error_node, gnat_entity, max_allowed_alignment);
@@ -6933,7 +6963,11 @@ validate_alignment (Uint alignment, Enti
gnat_error_node, gnat_entity,
align / BITS_PER_UNIT);
else
- align = MAX (align, new_align == 0 ? 1 : new_align * BITS_PER_UNIT);
+ {
+ new_align = (new_align > 0 ? new_align * BITS_PER_UNIT : 1);
+ if (new_align > align)
+ align = new_align;
+ }
return align;
}