]> gcc.gnu.org Git - gcc.git/commitdiff
[Ada] Fix predicate check on object declaration
authorMarc Poulhiès <poulhies@adacore.com>
Fri, 22 Apr 2022 15:52:49 +0000 (17:52 +0200)
committerPierre-Marie de Rodat <derodat@adacore.com>
Wed, 1 Jun 2022 08:43:19 +0000 (08:43 +0000)
When subtype predicate checks are added for object declarations, it
could lead to a compiler crash or to an incorrect check.

When the subtype for the object being declared is built later by
Analyze_Object_Declaration, the predicate check can't be applied on the
object instead of a copy as the call will be incorrect after the subtype
has been built.

When subtypes for LHS and RHS do not statically match, only checking the
predicate on the object after it has been initialized may miss a failing
predicate on the RHS.

In both cases, skip the optimization and check the predicate on a copy.

Rename Should_Build_Subtype into Build_Default_Subtype_OK and move it
out of sem_ch3 to make it available to other part of the compiler (in
particular to checks.adb).

gcc/ada/

* checks.adb (Apply_Predicate_Check): Refine condition for
applying optimization.
* sem_ch3.adb (Analyze_Component_Declaration): Adjust calls to
Should_Build_Subtype.
(Analyze_Object_Declaration): Likewise.
(Should_Build_Subtype): Rename/move to ...
* sem_util.ads (Build_Default_Subtype_OK): ... this.
* sem_util.adb (Build_Default_Subtype_OK): Moved from
sem_ch3.adb.

gcc/ada/checks.adb
gcc/ada/sem_ch3.adb
gcc/ada/sem_util.adb
gcc/ada/sem_util.ads

index 14f4f95f88ccabab945dc65498d87bcde66c48d6..204d13efc72144d16f2529f9f62d1cbce1ff9c3e 100644 (file)
@@ -2944,14 +2944,28 @@ package body Checks is
 
          --  Similarly, if the expression is an aggregate in an object
          --  declaration, apply it to the object after the declaration.
-         --  This is only necessary in rare cases of tagged extensions
-         --  initialized with an aggregate with an "others => <>" clause.
+
+         --  This is only necessary in cases of tagged extensions
+         --  initialized with an aggregate with an "others => <>" clause,
+         --  when the subtypes of LHS and RHS do not statically match or
+         --  when we know the object's type will be rewritten later.
+         --  The condition for the later is copied from the
+         --  Analyze_Object_Declaration procedure when it actually builds the
+         --  subtype.
 
          elsif Nkind (Par) = N_Object_Declaration then
-            Insert_Action_After (Par,
-              Make_Predicate_Check (Typ,
-                New_Occurrence_Of (Defining_Identifier (Par), Sloc (N))));
-            return;
+            if Subtypes_Statically_Match
+                 (Etype (Defining_Identifier (Par)), Typ)
+              and then (Nkind (N) = N_Extension_Aggregate
+                         or else (Is_Definite_Subtype (Typ)
+                                   and then Build_Default_Subtype_OK (Typ)))
+            then
+               Insert_Action_After (Par,
+                  Make_Predicate_Check (Typ,
+                    New_Occurrence_Of (Defining_Identifier (Par), Sloc (N))));
+               return;
+            end if;
+
          end if;
       end if;
 
index f91d3edfefd13cf3cacf53ca1c042c362ed3f9c0..2dbba159980bfcd21602c40277154628e9da6db9 100644 (file)
@@ -725,16 +725,6 @@ package body Sem_Ch3 is
    --  sets the flags SSO_Set_Low_By_Default/SSO_Set_High_By_Default according
    --  to the setting of Opt.Default_SSO.
 
-   function Should_Build_Subtype (T : Entity_Id) return Boolean;
-   --  When analyzing components or object declarations, it is possible, in
-   --  some cases, to build subtypes for discriminated types. This is
-   --  worthwhile to avoid the backend allocating the maximum possible size for
-   --  objects of the type.
-   --  In particular, when T is limited, the discriminants and therefore the
-   --  size of an object of type T cannot change. Furthermore, if T is definite
-   --  with statically initialized defaulted discriminants, we are able and
-   --  want to build a constrained subtype of the right size.
-
    procedure Signed_Integer_Type_Declaration (T : Entity_Id; Def : Node_Id);
    --  Create a new signed integer entity, and apply the constraint to obtain
    --  the required first named subtype of this type.
@@ -2214,7 +2204,7 @@ package body Sem_Ch3 is
 
       --  When possible, build the default subtype
 
-      if Should_Build_Subtype (T) then
+      if Build_Default_Subtype_OK (T) then
          declare
             Act_T : constant Entity_Id := Build_Default_Subtype (T, N);
 
@@ -4815,7 +4805,7 @@ package body Sem_Ch3 is
 
       --  When possible, build the default subtype
 
-      elsif Should_Build_Subtype (T) then
+      elsif Build_Default_Subtype_OK (T) then
          if No (E) then
             Act_T := Build_Default_Subtype (T, N);
          else
@@ -22963,80 +22953,6 @@ package body Sem_Ch3 is
       end if;
    end Set_Stored_Constraint_From_Discriminant_Constraint;
 
-   --------------------------
-   -- Should_Build_Subtype --
-   --------------------------
-
-   function Should_Build_Subtype (T : Entity_Id) return Boolean is
-
-      function Default_Discriminant_Values_Known_At_Compile_Time
-         (T : Entity_Id) return Boolean;
-         --  For an unconstrained type T, return False if the given type has a
-         --  discriminant with default value not known at compile time. Return
-         --  True otherwise.
-
-      ---------------------------------------------------------
-      -- Default_Discriminant_Values_Known_At_Compile_Time --
-      ---------------------------------------------------------
-
-      function Default_Discriminant_Values_Known_At_Compile_Time
-         (T : Entity_Id) return Boolean
-      is
-         Discr : Entity_Id;
-         DDV : Node_Id;
-
-      begin
-
-         --  If the type has no discriminant, we know them all at compile time
-
-         if not Has_Discriminants (T) then
-            return True;
-         end if;
-
-         --  The type has discriminants, check that none of them has a default
-         --  value not known at compile time.
-
-         Discr := First_Discriminant (T);
-
-         while Present (Discr) loop
-            DDV := Discriminant_Default_Value (Discr);
-
-            if Present (DDV) and then not Compile_Time_Known_Value (DDV) then
-               return False;
-            end if;
-
-            Next_Discriminant (Discr);
-         end loop;
-
-         return True;
-      end Default_Discriminant_Values_Known_At_Compile_Time;
-
-   --  Start of processing for Should_Build_Subtype
-
-   begin
-
-      if Is_Constrained (T) then
-
-         --  We won't build a new subtype if T is constrained
-
-         return False;
-      end if;
-
-      if not Default_Discriminant_Values_Known_At_Compile_Time (T) then
-
-         --  This is a special case of definite subtypes. To allocate a
-         --  specific size to the subtype, we need to know the value at compile
-         --  time. This might not be the case if the default value is the
-         --  result of a function. In that case, the object might be definite
-         --  and limited but the needed size might not be statically known or
-         --  too tricky to obtain. In that case, we will not build the subtype.
-
-         return False;
-      end if;
-
-      return Is_Definite_Subtype (T) and then Is_Limited_View (T);
-   end Should_Build_Subtype;
-
    -------------------------------------
    -- Signed_Integer_Type_Declaration --
    -------------------------------------
index 3ca19323eac6563d74dd8c8b254d5782a10a2012..eb0a1f1173351400a3c482655caf0de23ee3d442 100644 (file)
@@ -2533,6 +2533,80 @@ package body Sem_Util is
       end;
    end Build_Default_Subtype;
 
+   ------------------------------
+   -- Build_Default_Subtype_OK --
+   ------------------------------
+
+   function Build_Default_Subtype_OK (T : Entity_Id) return Boolean is
+
+      function Default_Discriminant_Values_Known_At_Compile_Time
+         (T : Entity_Id) return Boolean;
+         --  For an unconstrained type T, return False if the given type has a
+         --  discriminant with default value not known at compile time. Return
+         --  True otherwise.
+
+      ---------------------------------------------------------
+      -- Default_Discriminant_Values_Known_At_Compile_Time --
+      ---------------------------------------------------------
+
+      function Default_Discriminant_Values_Known_At_Compile_Time
+         (T : Entity_Id) return Boolean
+      is
+         Discr : Entity_Id;
+         DDV : Node_Id;
+
+      begin
+
+         --  If the type has no discriminant, we know them all at compile time
+
+         if not Has_Discriminants (T) then
+            return True;
+         end if;
+
+         --  The type has discriminants, check that none of them has a default
+         --  value not known at compile time.
+
+         Discr := First_Discriminant (T);
+
+         while Present (Discr) loop
+            DDV := Discriminant_Default_Value (Discr);
+
+            if Present (DDV) and then not Compile_Time_Known_Value (DDV) then
+               return False;
+            end if;
+
+            Next_Discriminant (Discr);
+         end loop;
+
+         return True;
+      end Default_Discriminant_Values_Known_At_Compile_Time;
+
+   --  Start of processing for Build_Default_Subtype_OK
+
+   begin
+
+      if Is_Constrained (T) then
+
+         --  We won't build a new subtype if T is constrained
+
+         return False;
+      end if;
+
+      if not Default_Discriminant_Values_Known_At_Compile_Time (T) then
+
+         --  This is a special case of definite subtypes. To allocate a
+         --  specific size to the subtype, we need to know the value at compile
+         --  time. This might not be the case if the default value is the
+         --  result of a function. In that case, the object might be definite
+         --  and limited but the needed size might not be statically known or
+         --  too tricky to obtain. In that case, we will not build the subtype.
+
+         return False;
+      end if;
+
+      return Is_Definite_Subtype (T) and then Is_Limited_View (T);
+   end Build_Default_Subtype_OK;
+
    --------------------------------------------
    -- Build_Discriminal_Subtype_Of_Component --
    --------------------------------------------
index bfd952a29477b587f6da4cbb962d71eca3fec577..37118ccb809c7ffbe5743c78fcea2a21f984617c 100644 (file)
@@ -320,6 +320,16 @@ package Sem_Util is
    --  declaration in the tree before N, and return the entity of that
    --  subtype. Otherwise, simply return T.
 
+   function Build_Default_Subtype_OK (T : Entity_Id) return Boolean;
+   --  When analyzing components or object declarations, it is possible, in
+   --  some cases, to build subtypes for discriminated types. This is
+   --  worthwhile to avoid the backend allocating the maximum possible size for
+   --  objects of the type.
+   --  In particular, when T is limited, the discriminants and therefore the
+   --  size of an object of type T cannot change. Furthermore, if T is definite
+   --  with statically initialized defaulted discriminants, we are able and
+   --  want to build a constrained subtype of the right size.
+
    function Build_Discriminal_Subtype_Of_Component
      (T : Entity_Id) return Node_Id;
    --  Determine whether a record component has a type that depends on
This page took 0.094989 seconds and 5 git commands to generate.