diff mbox

[Ada] Crash on config pragma Component_Alignment

Message ID 20160622104259.GA69486@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet June 22, 2016, 10:42 a.m. UTC
Pragma Component_Alignment was not implemented properly and caused a crash
when used in a configuration file due to how it was applied via the scope
table. This patch correctly identifies this case and uses a global variable
Configuration_Component_Alignment to capture the value set during
configuration analysis and applies it in place of the default value.

------------
-- Source --
------------

--  stor_unit.adc

pragma Component_Alignment (Form => Storage_Unit);

--  pack_storage_unit.ads

package Pack_Storage_Unit is
   pragma Component_Alignment (Form => Storage_Unit);

   type Small_Int is new Integer range 0 .. 1;
   for Small_Int'Size use 1;

   type Rec is record
      Comp_1 : Small_Int;
      Comp_2 : Small_Int;
      Comp_3 : Boolean;
      Comp_4 : Integer;
      Comp_5 : Long_Integer;
   end record;
end Pack_Storage_Unit;

--  pack.ads

package Pack is

   type Small_Int is new Integer range 0 .. 1;
   for Small_Int'Size use 1;

   type Rec is record
      Comp_1 : Small_Int;
      Comp_2 : Small_Int;
      Comp_3 : Boolean;
      Comp_4 : Integer;
      Comp_5 : Long_Integer;
   end record;
end Pack;

----------------------------
-- Compilation and output --
----------------------------

$ gcc -c -gnatR pack_storage_unit.ads > output1.txt
$ gcc -c -gnatR pack.ads -gnatec=stor_unit.adc > output2.txt
$ grep -v -F -x -f output1.txt output2.txt
Representation information for unit Pack (spec)
for Rec'Size use 128;
for Rec'Alignment use 8;
   Comp_4 at 4 range  0 .. 31;
   Comp_5 at 8 range  0 .. 63;

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

2016-06-22  Justin Squirek  <squirek@adacore.com>

	* sem_ch8.adb (Push_Scope): Add a check for when the
	scope table is empty to assign the global variable
	Configuration_Component_Alignment.
	* sem.adb (Do_Analyze): Add Configuration_Component_Alignment
	to be assigned when the environment is cleaned instead of the
	default.
	* sem.ads Add a global variable Configuration_Component_Alignment
	to store the value given by pragma Component_Alignment in the
	context of a configuration file.
	* sem_prag.adb (Analyze_Pragma): Correct the case for
	Component_Alignment so that the pragma is verified and add
	comments to explain how it is applied to the scope stack.
diff mbox

Patch

Index: sem.adb
===================================================================
--- sem.adb	(revision 237680)
+++ sem.adb	(working copy)
@@ -1355,7 +1355,8 @@ 
          Outer_Generic_Scope := Empty;
          Scope_Suppress      := Suppress_Options;
          Scope_Stack.Table
-           (Scope_Stack.Last).Component_Alignment_Default := Calign_Default;
+           (Scope_Stack.Last).Component_Alignment_Default :=
+             Configuration_Component_Alignment;
          Scope_Stack.Table
            (Scope_Stack.Last).Is_Active_Stack_Base := True;
 
Index: sem.ads
===================================================================
--- sem.ads	(revision 237680)
+++ sem.ads	(working copy)
@@ -461,6 +461,11 @@ 
    --  Transient blocks have three associated actions list, to be inserted
    --  before and after the block's statements, and as cleanup actions.
 
+   Configuration_Component_Alignment : Component_Alignment_Kind :=
+                                         Calign_Default;
+   --  Used for handling the pragma Component_Alignment in the context of a
+   --  configuration file.
+
    type Scope_Stack_Entry is record
       Entity : Entity_Id;
       --  Entity representing the scope
Index: sem_ch8.adb
===================================================================
--- sem_ch8.adb	(revision 237693)
+++ sem_ch8.adb	(working copy)
@@ -8192,10 +8192,22 @@ 
          SST.Save_Default_SSO              := Default_SSO;
          SST.Save_Uneval_Old               := Uneval_Old;
 
+         --  Each new scope pushed onto the scope stack inherits the component
+         --  alignment of the previous scope. This emulates the "visibility"
+         --  semantics of pragma Component_Alignment.
+
          if Scope_Stack.Last > Scope_Stack.First then
             SST.Component_Alignment_Default := Scope_Stack.Table
                                                  (Scope_Stack.Last - 1).
                                                    Component_Alignment_Default;
+
+         --  Otherwise, this is the first scope being pushed on the scope
+         --  stack. Inherit the component alignment from the configuration
+         --  form of pragma Component_Alignment (if any).
+
+         else
+            SST.Component_Alignment_Default :=
+              Configuration_Component_Alignment;
          end if;
 
          SST.Last_Subprogram_Name           := null;
Index: sem_prag.adb
===================================================================
--- sem_prag.adb	(revision 237693)
+++ sem_prag.adb	(working copy)
@@ -12787,9 +12787,21 @@ 
                  ("invalid Form parameter for pragma%", Form);
             end if;
 
+            --  The pragma appears in a configuration file
+
+            if No (Parent (N)) then
+               Check_Valid_Configuration_Pragma;
+
+               --  Capture the component alignment in a global variable when
+               --  the pragma appears in a configuration file. Note that the
+               --  scope stack is empty at this point and cannot be used to
+               --  store the alignment value.
+
+               Configuration_Component_Alignment := Atype;
+
             --  Case with no name, supplied, affects scope table entry
 
-            if No (Name) then
+            elsif No (Name) then
                Scope_Stack.Table
                  (Scope_Stack.Last).Component_Alignment_Default := Atype;
 
@@ -20901,7 +20913,7 @@ 
             Mode_Id := Get_SPARK_Mode_Type (Mode);
             Context := Parent (N);
 
-            --  The pragma appears in a configuration pragmas file
+            --  The pragma appears in a configuration file
 
             if No (Context) then
                Check_Valid_Configuration_Pragma;