Fix uninitialized variable in Atree.Size_In_Slots
authorBob Duff <duff@adacore.com>
Wed, 12 May 2021 09:56:47 +0000 (11:56 +0200)
committerEric Botcazou <ebotcazou@adacore.com>
Wed, 12 May 2021 10:15:55 +0000 (12:15 +0200)
Size_In_Slots uses the Nkind to look up the size in a table indexed
by Nkind.  This patch fixes a couple of places where the Nkind is
wrong (uninitialized or zeroed out) so Size_In_Slots cannot be used.

gcc/ada/
PR ada/100564
* atree.adb (Change_Node): Do not call Zero_Slots on a Node_Id
when the Nkind has not yet been set; call the other Zero_Slots
that takes a range of slot offsets.  Call the new Mutate_Kind
that takes an Old_Size, for the same reason -- the size cannot
be computed without the Nkind.
(Mutate_Nkind): New function that allows specifying the Old_Size.
(Size_In_Slots): Assert that the Nkind has proper (nonzero) value.
* atree.ads: Minor reformatting.

gcc/ada/atree.adb
gcc/ada/atree.ads

index 4d4dc43..608819b 100644 (file)
@@ -216,6 +216,13 @@ package body Atree is
    --  cannot be used to modify an already-initialized Nkind field. See also
    --  Mutate_Nkind.
 
+   procedure Mutate_Nkind
+     (N : Node_Id; Val : Node_Kind; Old_Size : Field_Offset);
+   --  Called by the other Mutate_Nkind to do all the work. This is needed
+   --  because the call in Change_Node, which calls this one directly, happens
+   --  after zeroing N's slots, which destroys its Nkind, which prevents us
+   --  from properly computing Old_Size.
+
    package Field_Checking is
       function Field_Present
         (Kind : Node_Kind; Field : Node_Field) return Boolean;
@@ -868,9 +875,8 @@ package body Atree is
    end Init_Nkind;
 
    procedure Mutate_Nkind
-     (N : Node_Id; Val : Node_Kind)
+     (N : Node_Id; Val : Node_Kind; Old_Size : Field_Offset)
    is
-      Old_Size : constant Field_Offset := Size_In_Slots (N);
       New_Size : constant Field_Offset := Size_In_Slots_To_Alloc (Val);
 
       All_Node_Offsets : Node_Offsets.Table_Type renames
@@ -905,6 +911,11 @@ package body Atree is
       pragma Debug (Validate_Node_Write (N));
    end Mutate_Nkind;
 
+   procedure Mutate_Nkind (N : Node_Id; Val : Node_Kind) is
+   begin
+      Mutate_Nkind (N, Val, Old_Size => Size_In_Slots (N));
+   end Mutate_Nkind;
+
    Ekind_Offset : constant Field_Offset :=
      Entity_Field_Descriptors (Ekind).Offset;
 
@@ -998,13 +1009,19 @@ package body Atree is
       end if;
 
       if New_Size > Old_Size then
-         pragma Debug (Zero_Slots (N));
-         Node_Offsets.Table (N) := Alloc_Slots (New_Size);
-      end if;
+         declare
+            New_Offset : constant Field_Offset := Alloc_Slots (New_Size);
+         begin
+            pragma Debug (Zero_Slots (N));
+            Node_Offsets.Table (N) := New_Offset;
+            Zero_Slots (New_Offset, New_Offset + New_Size - 1);
+         end;
 
-      Zero_Slots (N);
+      else
+         Zero_Slots (N);
+      end if;
 
-      Mutate_Nkind (N, New_Kind);
+      Mutate_Nkind (N, New_Kind, Old_Size);
 
       Set_Sloc (N, Save_Sloc);
       Set_In_List (N, Save_In_List);
@@ -2125,6 +2142,7 @@ package body Atree is
 
    function Size_In_Slots (N : Node_Or_Entity_Id) return Field_Offset is
    begin
+      pragma Assert (Nkind (N) /= N_Unused_At_Start);
       return
         (if Nkind (N) in N_Entity then Einfo.Entities.Max_Entity_Size
          else Sinfo.Nodes.Size (Nkind (N)));
index efb8ca2..e2d3492 100644 (file)
@@ -571,8 +571,7 @@ package Atree is
      (N : Entity_Id; Field : Entity_Field) return Boolean;
    --  True if the field value is the initial zero value
 
-   procedure Mutate_Nkind
-     (N : Node_Id; Val : Node_Kind) with Inline;
+   procedure Mutate_Nkind (N : Node_Id; Val : Node_Kind) with Inline;
    --  There is no Set_Nkind in Sinfo.Nodes. We use this instead. This is here,
    --  and has a different name, because it does some extra checking. Nkind is
    --  like a discriminant, in that it controls which fields exist, and that