[Ada] Warning if record size is not a multiple of alignment

Arnaud Charlet charlet@adacore.com
Wed Jul 16 14:35:00 GMT 2014


This implements a new warning (on by default, controlled
by -gnatw.z/-gnatw.Z, included in -gnatwa), that warns
if a record type has a specified size and alignment where
the size is not a multiple of the alignment resulting in
an object size greater than the specified size.

The warning is suppressed if an explicit value is given
for the object size.

THe following test:

     1. package SizeAlign is
     2.    type R1 is record
     3.       A,B,C,D,E : Integer;
     4.    end record;
     5.    for R1'Size use 5*32;
     6.    for R1'Alignment use 8;
           |
        >>> warning: size is not a multiple of alignment for "R1"
        >>> warning: size of 160 specified at line 5
        >>> warning: Object_Size will be increased to 192

     7.
     8.    type R2 is record
     9.       A,B,C,D,E : Integer;
    10.    end record;
    11.    for R2'Alignment use 8;
    12.    for R2'Size use 5*32;
           |
        >>> warning: size is not a multiple of alignment for "R2"
        >>> warning: alignment of 8 specified at line 11
        >>> warning: Object_Size will be increased to 192

    13.
    14.    type R3 is record
    15.       A,B,C,D,E : Integer;
    16.    end record;
    17.    for R3'Alignment use 8;
    18.    for R3'Size use 5*32;
    19.    for R3'Object_Size use 192;
    20. end;

generates the given warnings, with the -gnatR2 output of:

Representation information for unit Sizealign (spec)

for R1'Object_Size use 192;
for R1'Value_Size use 160;
for R1'Alignment use 8;
for R1 use record
   A at  0 range  0 .. 31;
   B at  4 range  0 .. 31;
   C at  8 range  0 .. 31;
   D at 12 range  0 .. 31;
   E at 16 range  0 .. 31;
end record;

for R2'Object_Size use 192;
for R2'Value_Size use 160;
for R2'Alignment use 8;
for R2 use record
   A at  0 range  0 .. 31;
   B at  4 range  0 .. 31;
   C at  8 range  0 .. 31;
   D at 12 range  0 .. 31;
   E at 16 range  0 .. 31;
end record;

Tested on x86_64-pc-linux-gnu, committed on trunk

2014-07-16  Robert Dewar  <dewar@adacore.com>

	* freeze.adb (Freeze_Entity): Warn on incompatible size/alignment.
	* gnat_ugn.texi: Document -gnatw.z and -gnatw.Z.
	* ug_words: VMS synonyms (WARNINGS=[NO]SIZE_ALIGN) for -gnatw.z/-gnatw.Z
	* usage.adb: Add lines for -gnatw.z/-gnatw.Z.
	* vms_data.ads: VMS synonyms (WARNINGS=[NO]SIZE_ALIGN) for
	-gnatw.z/-gnatw.Z
	* warnsw.adb: Set Warn_On_Size_Alignment appropriately.
	* warnsw.ads (Warn_On_Size_Alignment): New flag Minor
	reformatting.

-------------- next part --------------
Index: usage.adb
===================================================================
--- usage.adb	(revision 212640)
+++ usage.adb	(working copy)
@@ -503,7 +503,7 @@
    Write_Line ("        F*   turn off warnings for unreferenced formal");
    Write_Line ("        g*+  turn on warnings for unrecognized pragma");
    Write_Line ("        G    turn off warnings for unrecognized pragma");
-   Write_Line ("        .g   turn on GNAT warnings, same as Aao.sI.C.V.X");
+   Write_Line ("        .g   turn on GNAT warnings");
    Write_Line ("        h    turn on warnings for hiding declarations");
    Write_Line ("        H*   turn off warnings for hiding declarations");
    Write_Line ("        .h   turn on warnings for holes in records");
@@ -589,6 +589,10 @@
                                                   "unchecked conversion");
    Write_Line ("        Z    turn off warnings for suspicious " &
                                                   "unchecked conversion");
+   Write_Line ("        .z*+ turn on warnings for record size not a " &
+                                                  "multiple of alignment");
+   Write_Line ("        .Z   turn off warnings for record size not a " &
+                                                  "multiple of alignment");
 
    --  Line for -gnatW switch
 
Index: ug_words
===================================================================
--- ug_words	(revision 212640)
+++ ug_words	(working copy)
@@ -226,6 +226,8 @@
 -gnatw.Y        ^ /WARNINGS=NOWHY_SPEC_NEEDS_BODY
 -gnatwz         ^ /WARNINGS=UNCHECKED_CONVERSIONS
 -gnatwZ         ^ /WARNINGS=NOUNCHECKED_CONVERSIONS
+-gnatw.z        ^ /WARNINGS=SIZE_ALIGN
+-gnatw.Z        ^ /WARNINGS=NOSIZE_ALIGN
 -gnatW8         ^ /WIDE_CHARACTER_ENCODING=UTF8
 -gnatW?         ^ /WIDE_CHARACTER_ENCODING=?
 -gnaty          ^ /STYLE_CHECKS
Index: gnat_ugn.texi
===================================================================
--- gnat_ugn.texi	(revision 212654)
+++ gnat_ugn.texi	(working copy)
@@ -4798,6 +4798,9 @@
 Possible order of elaboration problems
 
 @item
+Size not a multiple of alignment for a record type
+
+@item
 Assertions (pragma Assert) that are sure to fail
 
 @item
@@ -5869,6 +5872,28 @@
 where the types are known at compile time to have different
 sizes or conventions.
 
+@item -gnatw.z
+@emph{Activate warnings for size not a multiple of alignment.}
+@cindex @option{-gnatw.z} (@command{gcc})
+@cindex Size/Alignment warnings
+This switch activates warnings for cases of record types with
+specified @code{Size} and @code{Alignment} attributes where the
+size is not a multiple of the alignment, resulting in an object
+size that is greater than the specified size. The default
+is that such warnings are generated.
+This warning can also be turned on using @option{-gnatwa}.
+
+@item -gnatw.Z
+@emph{Suppress warnings for size not a multiple of alignment.}
+@cindex @option{-gnatw.Z} (@command{gcc})
+@cindex Size/Alignment warnings
+This switch suppresses warnings for cases of record types with
+specified @code{Size} and @code{Alignment} attributes where the
+size is not a multiple of the alignment, resulting in an object
+size that is greater than the specified size.
+The warning can also be
+suppressed by giving an explicit @code{Object_Size} value.
+
 @item ^-Wunused^WARNINGS=UNUSED^
 @cindex @option{-Wunused}
 The warnings controlled by the @option{-gnatw} switch are generated by
Index: freeze.adb
===================================================================
--- freeze.adb	(revision 212640)
+++ freeze.adb	(working copy)
@@ -64,6 +64,7 @@
 with Ttypes;   use Ttypes;
 with Uintp;    use Uintp;
 with Urealp;   use Urealp;
+with Warnsw;   use Warnsw;
 
 package body Freeze is
 
@@ -4554,6 +4555,55 @@
             Inherit_Aspects_At_Freeze_Point (E);
          end if;
 
+         --  Check for incompatible size and alignment for record type
+
+         if Warn_On_Size_Alignment
+           and then Is_Record_Type (E)
+           and then Has_Size_Clause (E) and then Has_Alignment_Clause (E)
+
+           --  If explicit Object_Size clause given assume that the programmer
+           --  knows what he is doing, and expects the compiler behavior.
+
+           and then not Has_Object_Size_Clause (E)
+
+           --  Check for size not a multiple of alignment
+
+           and then RM_Size (E) mod (Alignment (E) * System_Storage_Unit) /= 0
+         then
+            declare
+               SC    : constant Node_Id := Size_Clause (E);
+               AC    : constant Node_Id := Alignment_Clause (E);
+               Loc   : Node_Id;
+               Abits : constant Uint := Alignment (E) * System_Storage_Unit;
+
+            begin
+               if Present (SC) and then Present (AC) then
+
+                  --  Give a warning
+
+                  if Sloc (SC) > Sloc (AC) then
+                     Loc := SC;
+                     Error_Msg_NE
+                       ("??size is not a multiple of alignment for &", Loc, E);
+                     Error_Msg_Sloc := Sloc (AC);
+                     Error_Msg_Uint_1 := Alignment (E);
+                     Error_Msg_N ("\??alignment of ^ specified #", Loc);
+
+                  else
+                     Loc := AC;
+                     Error_Msg_NE
+                       ("??size is not a multiple of alignment for &", Loc, E);
+                     Error_Msg_Sloc := Sloc (SC);
+                     Error_Msg_Uint_1 := RM_Size (E);
+                     Error_Msg_N ("\??size of ^ specified #", Loc);
+                  end if;
+
+                  Error_Msg_Uint_1 := ((RM_Size (E) / Abits) + 1) * Abits;
+                  Error_Msg_N ("\??Object_Size will be increased to ^", Loc);
+               end if;
+            end;
+         end if;
+
          --  Array type
 
          if Is_Array_Type (E) then
Index: warnsw.adb
===================================================================
--- warnsw.adb	(revision 212640)
+++ warnsw.adb	(working copy)
@@ -78,6 +78,7 @@
       Warn_On_Record_Holes                := Setting;
       Warn_On_Redundant_Constructs        := Setting;
       Warn_On_Reverse_Bit_Order           := Setting;
+      Warn_On_Size_Alignment              := Setting;
       Warn_On_Standard_Redefinition       := Setting;
       Warn_On_Suspicious_Contract         := Setting;
       Warn_On_Suspicious_Modulus_Value    := Setting;
@@ -170,6 +171,8 @@
         W.Warn_On_Redundant_Constructs;
       Warn_On_Reverse_Bit_Order           :=
         W.Warn_On_Reverse_Bit_Order;
+      Warn_On_Size_Alignment              :=
+        W.Warn_On_Size_Alignment;
       Warn_On_Standard_Redefinition       :=
         W.Warn_On_Standard_Redefinition;
       Warn_On_Suspicious_Contract         :=
@@ -270,6 +273,8 @@
         Warn_On_Redundant_Constructs;
       W.Warn_On_Reverse_Bit_Order           :=
         Warn_On_Reverse_Bit_Order;
+      W.Warn_On_Size_Alignment              :=
+        Warn_On_Size_Alignment;
       W.Warn_On_Standard_Redefinition       :=
         Warn_On_Standard_Redefinition;
       W.Warn_On_Suspicious_Contract         :=
@@ -421,6 +426,12 @@
          when 'Y' =>
             List_Body_Required_Info             := False;
 
+         when 'z' =>
+            Warn_On_Size_Alignment              := True;
+
+         when 'Z' =>
+            Warn_On_Size_Alignment              := False;
+
          when others =>
             if Ignore_Unrecognized_VWY_Switches then
                Write_Line ("unrecognized switch -gnatw." & C & " ignored");
@@ -454,6 +465,7 @@
       Warn_On_Non_Local_Exception         := False;
       No_Warn_On_Non_Local_Exception      := True;
       Warn_On_Reverse_Bit_Order           := False;
+      Warn_On_Size_Alignment              := False;
       Warn_On_Unrepped_Components         := False;
    end Set_GNAT_Mode_Warnings;
 
@@ -660,6 +672,7 @@
       Warn_On_Questionable_Missing_Parens := True;
       Warn_On_Redundant_Constructs        := True;
       Warn_On_Reverse_Bit_Order           := True;
+      Warn_On_Size_Alignment              := True;
       Warn_On_Suspicious_Contract         := True;
       Warn_On_Unchecked_Conversion        := True;
       Warn_On_Unrecognized_Pragma         := True;
Index: warnsw.ads
===================================================================
--- warnsw.ads	(revision 212640)
+++ warnsw.ads	(working copy)
@@ -44,14 +44,19 @@
 
    Warn_On_Overridden_Size : Boolean := False;
    --  Warn when explicit record component clause or array component_size
-   --  clause specifies a size that overrides a size for the typen which was
+   --  clause specifies a size that overrides a size for the type which was
    --  set with an explicit size clause. Off by default, modified by use of
-   --  -gnatw.s/.S, but not set by -gnatwa.
+   --  -gnatw.s/.S (but not -gnatwa).
 
+   Warn_On_Size_Alignment : Boolean := True;
+   --  Warn when explicit Size and Alignment clauses are given for a type, and
+   --  the size is not a multiple of the alignment. Off by default, modified
+   --  by use of -gnatw.z/.Z and set as part of -gnatwa.
+
    Warn_On_Standard_Redefinition : Boolean := False;
    --  Warn when a program defines an identifier that matches a name in
-   --  Standard. Off by default, modified by use of -gnatw.k/.K, but not
-   --  affected by -gnatwa.
+   --  Standard. Off by default, modified by use of -gnatw.k/.K (but not
+   --  by -gnatwa).
 
    -----------------------------------
    -- Saving and Restoring Warnings --
@@ -98,6 +103,7 @@
       Warn_On_Record_Holes                : Boolean;
       Warn_On_Redundant_Constructs        : Boolean;
       Warn_On_Reverse_Bit_Order           : Boolean;
+      Warn_On_Size_Alignment              : Boolean;
       Warn_On_Standard_Redefinition       : Boolean;
       Warn_On_Suspicious_Contract         : Boolean;
       Warn_On_Suspicious_Modulus_Value    : Boolean;
Index: vms_data.ads
===================================================================
--- vms_data.ads	(revision 212640)
+++ vms_data.ads	(working copy)
@@ -3270,7 +3270,12 @@
                                             "UNCHECKED_CONVERSIONS "       &
                                                "-gnatwz "                  &
                                             "NOUNCHECKED_CONVERSIONS "     &
-                                               "-gnatwZ";
+                                               "-gnatwZ"                   &
+                                            "SIZE_ALIGNMENT "              &
+                                               "-gnatw.z"                  &
+                                            "NOSIZE_ALIGNMENT "            &
+                                               "-gnatw.Z";
+
    --        /NOWARNINGS
    --
    --   Suppress the output of all warning messages from the GNAT front end.
@@ -3300,6 +3305,7 @@
    --                               MISSING_PARENS
    --                               OVERLAPPING_ACTUALS
    --                               REVERSE_BIT_ORDER
+   --                               SIZE_ALIGNMENT
    --                               SUSPICIOUS_CONTRACT
    --                               SUSPICIOUS_MODULUS
    --                               UNCHECKED_CONVERSIONS
@@ -3589,6 +3595,12 @@
    --                           effect of specifying reverse bit order for
    --                           a record on individual components.
    --
+   --   SIZE_ALIGNMENT          Activates warnings for record types for which
+   --   (-gnatw.z)              explicit size and alignment values are given,
+   --                           where the size value is not a multiple of the
+   --                           alignment value, resulting in an object size
+   --                           larger than the specified size.
+   --
    --   STANDARD_REDEFINITION   Activate warnings on standard redefinition.
    --   (-gnatw.k)              Generates a warning message if a declaration
    --                           declares an identifier that matches one that


More information about the Gcc-patches mailing list