When using 'Valid_Scalars on unconstrained arrays, the expanded code
includes unchecked conversion to the unconstrained base type, which may
lead to incorrect code being generated.
Fixed by replacing Validated_View by Get_Fullest_View except for records
where it is still needed.

We also take this opportunity to evaluate at compile time many more
cases of 'Valid expansion, in particular related to indexed components
which were never evaluated at compile time.

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

gcc/ada/

        * exp_attr.adb (Build_Array_VS_Func, Build_Record_VS_Func,
        Expand_N_Attribute_Reference): Use Get_Fullest_View instead of
        Validated_View.
        (Build_Record_VS_Func): Adjust to keep using Validated_View.
        (Expand_N_Attribute_Reference) [Valid]: Use
        Small_Integer_Type_For to allow for more compile time
        evaluations.
        * sem_util.adb (Cannot_Raise_Constraint_Error): Add more precise
        support for N_Indexed_Component and fix support for
        N_Selected_Component which wasn't completely safe.
        (List_Cannot_Raise_CE): New.
        * libgnat/i-cobol.adb (Valid_Packed): Simplify test to address
        new GNAT warning.
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -244,7 +244,7 @@ package body Exp_Attr is
    is
       Loc      : constant Source_Ptr := Sloc (Attr);
       Comp_Typ : constant Entity_Id :=
-        Validated_View (Component_Type (Array_Typ));
+        Get_Fullest_View (Component_Type (Array_Typ));
 
       function Validate_Component
         (Obj_Id  : Entity_Id;
@@ -531,7 +531,7 @@ package body Exp_Attr is
       is
          Field_Id  : constant Entity_Id := Defining_Entity (Field);
          Field_Nam : constant Name_Id   := Chars (Field_Id);
-         Field_Typ : constant Entity_Id := Validated_View (Etype (Field_Id));
+         Field_Typ : constant Entity_Id := Get_Fullest_View (Etype (Field_Id));
          Attr_Nam  : Name_Id;
 
       begin
@@ -733,7 +733,7 @@ package body Exp_Attr is
    --  Start of processing for Build_Record_VS_Func
 
    begin
-      Typ := Rec_Typ;
+      Typ := Validated_View (Rec_Typ);
 
       --  Use the root type when dealing with a class-wide type
 
@@ -7329,7 +7329,7 @@ package body Exp_Attr is
          --  of the size of the type, not the range of the values). We write
          --  this as two tests, rather than a range check, so that static
          --  evaluation will easily remove either or both of the checks if
-         --  they can be -statically determined to be true (this happens
+         --  they can be statically determined to be true (this happens
          --  when the type of X is static and the range extends to the full
          --  range of stored values).
 
@@ -7350,12 +7350,39 @@ package body Exp_Attr is
 
          else
             declare
-               Uns : constant Boolean
-                       := Is_Unsigned_Type (Ptyp)
-                            or else (Is_Private_Type (Ptyp)
-                                      and then Is_Unsigned_Type (Btyp));
+               Uns  : constant Boolean :=
+                        Is_Unsigned_Type (Ptyp)
+                          or else (Is_Private_Type (Ptyp)
+                                    and then Is_Unsigned_Type (Btyp));
+               Size : Uint;
+               P    : Node_Id := Pref;
+
             begin
-               PBtyp := Integer_Type_For (Esize (Ptyp), Uns);
+               --  If the prefix has an entity, use the Esize from this entity
+               --  to handle in a more user friendly way the case of objects
+               --  or components with a large Size aspect: if a Size aspect is
+               --  specified, we want to read a scalar value as large as the
+               --  Size, unless the Size is larger than
+               --  System_Max_Integer_Size.
+
+               if Nkind (P) = N_Selected_Component then
+                  P := Selector_Name (P);
+               end if;
+
+               if Nkind (P) in N_Has_Entity
+                 and then Present (Entity (P))
+                 and then Esize (Entity (P)) /= Uint_0
+               then
+                  if Esize (Entity (P)) <= System_Max_Integer_Size then
+                     Size := Esize (Entity (P));
+                  else
+                     Size := UI_From_Int (System_Max_Integer_Size);
+                  end if;
+               else
+                  Size := Esize (Ptyp);
+               end if;
+
+               PBtyp := Small_Integer_Type_For (Size, Uns);
                Rewrite (N, Make_Range_Test);
             end;
          end if;
@@ -7385,7 +7412,7 @@ package body Exp_Attr is
       -------------------
 
       when Attribute_Valid_Scalars => Valid_Scalars : declare
-         Val_Typ : constant Entity_Id := Validated_View (Ptyp);
+         Val_Typ : constant Entity_Id := Get_Fullest_View (Ptyp);
          Expr    : Node_Id;
 
       begin


diff --git a/gcc/ada/libgnat/i-cobol.adb b/gcc/ada/libgnat/i-cobol.adb
--- a/gcc/ada/libgnat/i-cobol.adb
+++ b/gcc/ada/libgnat/i-cobol.adb
@@ -692,7 +692,7 @@ package body Interfaces.COBOL is
             --  For signed, accept all standard and non-standard signs
 
             else
-               return Item (Item'Last) in 16#A# .. 16#F#;
+               return Item (Item'Last) >= 16#A#;
             end if;
       end case;
    end Valid_Packed;


diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -2900,6 +2900,32 @@ package body Sem_Util is
    -----------------------------------
 
    function Cannot_Raise_Constraint_Error (Expr : Node_Id) return Boolean is
+
+      function List_Cannot_Raise_CE (L : List_Id) return Boolean;
+      --  Returns True if none of the list members cannot possibly raise
+      --  Constraint_Error.
+
+      --------------------------
+      -- List_Cannot_Raise_CE --
+      --------------------------
+
+      function List_Cannot_Raise_CE (L : List_Id) return Boolean is
+         N : Node_Id;
+      begin
+         N := First (L);
+         while Present (N) loop
+            if Cannot_Raise_Constraint_Error (N) then
+               Next (N);
+            else
+               return False;
+            end if;
+         end loop;
+
+         return True;
+      end List_Cannot_Raise_CE;
+
+   --  Start of processing for Cannot_Raise_Constraint_Error
+
    begin
       if Compile_Time_Known_Value (Expr) then
          return True;
@@ -2918,8 +2944,14 @@ package body Sem_Util is
             when N_Expanded_Name =>
                return True;
 
+            when N_Indexed_Component =>
+               return not Do_Range_Check (Expr)
+                 and then Cannot_Raise_Constraint_Error (Prefix (Expr))
+                 and then List_Cannot_Raise_CE (Expressions (Expr));
+
             when N_Selected_Component =>
-               return not Do_Discriminant_Check (Expr);
+               return not Do_Discriminant_Check (Expr)
+                 and then Cannot_Raise_Constraint_Error (Prefix (Expr));
 
             when N_Attribute_Reference =>
                if Do_Overflow_Check (Expr) then
@@ -2929,21 +2961,7 @@ package body Sem_Util is
                   return True;
 
                else
-                  declare
-                     N : Node_Id;
-
-                  begin
-                     N := First (Expressions (Expr));
-                     while Present (N) loop
-                        if Cannot_Raise_Constraint_Error (N) then
-                           Next (N);
-                        else
-                           return False;
-                        end if;
-                     end loop;
-
-                     return True;
-                  end;
+                  return List_Cannot_Raise_CE (Expressions (Expr));
                end if;
 
             when N_Type_Conversion =>


Reply via email to