This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]