decl.c (gnat_to_gnu_entity): Issue a warning on suspiciously large alignments specifi...
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 7 Mar 2008 17:45:09 +0000 (17:45 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 7 Mar 2008 17:45:09 +0000 (17:45 +0000)
* decl.c (gnat_to_gnu_entity): Issue a warning on suspiciously
large alignments specified for types.
(validate_alignment): Minor cleanup.

From-SVN: r133012

gcc/ada/ChangeLog
gcc/ada/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/specs/alignment2.ads [new file with mode: 0644]

index 44879fd8c7bea4e885eed8024058e9838ee60da5..9d92d7b732f5efde269b549ace2a5b5cfb61a8b6 100644 (file)
@@ -1,3 +1,9 @@
+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>
 
        * decl.c (MAX_FIXED_MODE_SIZE): Define if not already defined.
index 7c75666f5d4390664d802e8ac6d7c870a2512f67..48279391b3079c45540460979aacf69336160683 100644 (file)
@@ -4086,8 +4086,38 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
       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 size_tree, bool biased_p)
 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, Entity_Id gnat_entity, unsigned int align)
                       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;
 }
index 1a5302d2486e2bca1f102fd2532ea84459b68239..5a6735d7df436f0ff2fd14448a5917a3c00800e1 100644 (file)
@@ -1,3 +1,7 @@
+2008-03-07  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/specs/alignment2.ads: New test.
+
 2008-03-07  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/pack3.adb: New test.
diff --git a/gcc/testsuite/gnat.dg/specs/alignment2.ads b/gcc/testsuite/gnat.dg/specs/alignment2.ads
new file mode 100644 (file)
index 0000000..1b92000
--- /dev/null
@@ -0,0 +1,45 @@
+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;