[gcc r12-1450] [Ada] Fix bug in subtype of private type with invariants

Pierre-Marie de Rodat pmderodat@gcc.gnu.org
Tue Jun 15 10:20:40 GMT 2021


https://gcc.gnu.org/g:a5db70e78af095a3d8e4744f21059448056fa47b

commit r12-1450-ga5db70e78af095a3d8e4744f21059448056fa47b
Author: Bob Duff <duff@adacore.com>
Date:   Sat Feb 13 16:43:22 2021 -0500

    [Ada] Fix bug in subtype of private type with invariants
    
    gcc/ada/
    
            * sem_util.adb (Propagate_Invariant_Attributes): Call
            Set_Has_Own_Invariants on the base type, because these are
            Base_Type_Only. The problem is that the base type of a type is
            indeed a base type when Set_Base_Type is called, but then the
            type is mutated into a subtype in rare cases.
            * atree.ads, atree.adb (Is_Entity): Export. Correct subtype of
            parameter in body.
            * gen_il-gen.adb: Improve getters so that "Pre => ..." can refer
            to the value of the field. Put Warnings (Off) on some with
            clauses that are not currently used, but might be used by such
            Pre's.

Diff:
---
 gcc/ada/atree.adb      |  6 +-----
 gcc/ada/atree.ads      |  4 ++++
 gcc/ada/gen_il-gen.adb | 44 +++++++++++++++++++++++++++++++-------------
 gcc/ada/sem_util.adb   |  6 ++++--
 4 files changed, 40 insertions(+), 20 deletions(-)

diff --git a/gcc/ada/atree.adb b/gcc/ada/atree.adb
index 608819bd1ad..541655c466f 100644
--- a/gcc/ada/atree.adb
+++ b/gcc/ada/atree.adb
@@ -139,10 +139,6 @@ package body Atree is
    -- Local Subprograms --
    -----------------------
 
-   function Is_Entity (N : Node_Or_Entity_Id) return Boolean;
-   pragma Inline (Is_Entity);
-   --  Returns True if N is an entity
-
    function Allocate_New_Node (Kind : Node_Kind) return Node_Id;
    pragma Inline (Allocate_New_Node);
    --  Allocate a new node or first part of a node extension. Initialize the
@@ -1435,7 +1431,7 @@ package body Atree is
    -- Is_Entity --
    ---------------
 
-   function Is_Entity (N : Node_Id) return Boolean is
+   function Is_Entity (N : Node_Or_Entity_Id) return Boolean is
    begin
       return Nkind (N) in N_Entity;
    end Is_Entity;
diff --git a/gcc/ada/atree.ads b/gcc/ada/atree.ads
index e2d3492e32f..c814c80cefa 100644
--- a/gcc/ada/atree.ads
+++ b/gcc/ada/atree.ads
@@ -222,6 +222,10 @@ package Atree is
    --  Called to unlock node modifications when assertions are enabled; if
    --  assertions are not enabled calling this subprogram has no effect.
 
+   function Is_Entity (N : Node_Or_Entity_Id) return Boolean;
+   pragma Inline (Is_Entity);
+   --  Returns True if N is an entity
+
    function New_Node
      (New_Node_Kind : Node_Kind;
       New_Sloc      : Source_Ptr) return Node_Id;
diff --git a/gcc/ada/gen_il-gen.adb b/gcc/ada/gen_il-gen.adb
index 5b2a17bca33..70557296a03 100644
--- a/gcc/ada/gen_il-gen.adb
+++ b/gcc/ada/gen_il-gen.adb
@@ -1508,20 +1508,31 @@ package body Gen_IL.Gen is
       end Put_Getter_Decl;
 
       procedure Put_Getter_Body (S : in out Sink'Class; F : Field_Enum) is
+         Rec : Field_Info renames Field_Table (F).all;
       begin
+         --  Note that we store the result in a local constant below, so that
+         --  the "Pre => ..." can refer to it. The constant is called Val so
+         --  that it has the same name as the formal of the setter, so the
+         --  "Pre => ..." can refer to it by the same name in both getter
+         --  and setter.
+
          Put_Getter_Spec (S, F);
          Put (S, " is\n");
+         Indent (S, 3);
+         Put (S, "Val : constant \1 := \2 (\3, \4);\n",
+              Get_Set_Id_Image (Rec.Field_Type),
+              Low_Level_Getter (Rec.Field_Type),
+              Node_To_Fetch_From (F),
+              Image (Rec.Offset));
+         Outdent (S, 3);
          Put (S, "begin\n");
          Indent (S, 3);
 
-         if Field_Table (F).Pre.all /= "" then
-            Put (S, "pragma Assert (\1);\n", Field_Table (F).Pre.all);
+         if Rec.Pre.all /= "" then
+            Put (S, "pragma Assert (\1);\n", Rec.Pre.all);
          end if;
 
-         Put (S, "return \1 (\2, \3);\n",
-              Low_Level_Getter (Field_Table (F).Field_Type),
-              Node_To_Fetch_From (F),
-              Image (Field_Table (F).Offset));
+         Put (S, "return Val;\n");
          Outdent (S, 3);
          Put (S, "end \1;\n\n", Image (F));
       end Put_Getter_Body;
@@ -1529,7 +1540,7 @@ package body Gen_IL.Gen is
       procedure Put_Setter_Spec (S : in out Sink'Class; F : Field_Enum) is
          Rec    : Field_Info renames Field_Table (F).all;
          Default : constant String :=
-           (if Field_Table (F).Field_Type = Flag then " := True" else "");
+           (if Rec.Field_Type = Flag then " := True" else "");
       begin
          Put (S, "procedure Set_\1\n", Image (F));
          Indent (S, 2);
@@ -1550,11 +1561,13 @@ package body Gen_IL.Gen is
       end Put_Setter_Decl;
 
       procedure Put_Setter_Body (S : in out Sink'Class; F : Field_Enum) is
+         Rec : Field_Info renames Field_Table (F).all;
+
          --  If Type_Only was specified in the call to Create_Semantic_Field,
          --  then we assert that the node is a base (etc) type.
 
          Type_Only_Assertion : constant String :=
-           (case Field_Table (F).Type_Only is
+           (case Rec.Type_Only is
               when No_Type_Only => "",
               when Base_Type_Only => "Is_Base_Type (N)",
 --  ????It seems like we should call Is_Implementation_Base_Type or
@@ -1570,8 +1583,8 @@ package body Gen_IL.Gen is
          Put (S, "begin\n");
          Indent (S, 3);
 
-         if Field_Table (F).Pre.all /= "" then
-            Put (S, "pragma Assert (\1);\n", Field_Table (F).Pre.all);
+         if Rec.Pre.all /= "" then
+            Put (S, "pragma Assert (\1);\n", Rec.Pre.all);
          end if;
 
          if Type_Only_Assertion /= "" then
@@ -1580,7 +1593,7 @@ package body Gen_IL.Gen is
 
          Put (S, "\1 (N, \2, Val);\n",
               Low_Level_Setter (F),
-              Image (Field_Table (F).Offset));
+              Image (Rec.Offset));
          Outdent (S, 3);
          Put (S, "end Set_\1;\n\n", Image (F));
       end Put_Setter_Body;
@@ -2034,9 +2047,11 @@ package body Gen_IL.Gen is
 
       begin
          Put (S, "with Seinfo; use Seinfo;\n");
-         Put (S, "pragma Warnings (Off); -- ????\n");
+         Put (S, "pragma Warnings (Off);\n");
+         --  With's included in case they are needed; so we don't have to keep
+         --  switching back and forth.
          Put (S, "with Output; use Output;\n");
-         Put (S, "pragma Warnings (On); -- ????\n");
+         Put (S, "pragma Warnings (On);\n");
 
          Put (S, "\npackage Sinfo.Nodes is\n\n");
          Indent (S, 3);
@@ -2061,6 +2076,9 @@ package body Gen_IL.Gen is
 
          Put (B, "with Atree; use Atree; use Atree.Atree_Private_Part;\n");
          Put (B, "with Nlists; use Nlists;\n");
+         Put (B, "pragma Warnings (Off);\n");
+         Put (B, "with Einfo.Utils; use Einfo.Utils;\n");
+         Put (B, "pragma Warnings (On);\n");
 
          Put (B, "\npackage body Sinfo.Nodes is\n\n");
          Indent (B, 3);
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 73a7bd1b20e..01690f3a35e 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -26215,7 +26215,9 @@ package body Sem_Util is
          Part_IP := Partial_Invariant_Procedure (From_Typ);
 
          --  The setting of the attributes is intentionally conservative. This
-         --  prevents accidental clobbering of enabled attributes.
+         --  prevents accidental clobbering of enabled attributes. We need to
+         --  call Base_Type twice, because it is sometimes not set to an actual
+         --  base type.
 
          if Has_Inheritable_Invariants (From_Typ) then
             Set_Has_Inheritable_Invariants (Typ);
@@ -26226,7 +26228,7 @@ package body Sem_Util is
          end if;
 
          if Has_Own_Invariants (From_Typ) then
-            Set_Has_Own_Invariants (Base_Type (Typ));
+            Set_Has_Own_Invariants (Base_Type (Base_Type (Typ)));
          end if;
 
          if Present (Full_IP) and then No (Invariant_Procedure (Typ)) then


More information about the Gcc-cvs mailing list