[Ada] Initialize_Scalars optimization causes spurious runtime check failure

This patch suppresses the optimization of scalar arrays when pragma
Initialize_Scalars is in effect if the component type is subject to
predicates. Since the scalar array is initialized with invalid values,
these values may violate the predicate or a validity check within the
predicate.

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

--  gnat.adc

pragma Initialize_Scalars;

--  types.ads

with System; use System;

package Types is
   type Byte is mod System.Storage_Unit;

   subtype Inter_Byte is Byte;

   function Always_OK (B : Inter_Byte) return Boolean is (True);
   function Is_OK     (B : Inter_Byte) return Boolean is (Always_OK (B));

   subtype Final_Byte is Byte with Predicate => Is_OK (Final_Byte);

   type Bytes is array (1 .. 5) of Final_Byte;

   Obj : Bytes;
end Types;

--  main.adb

with Types; use Types;

procedure Main is begin null; end Main;

-----------------
-- Compilation --
-----------------

$ gnatmake -q -gnata -gnatVa main.adb
$ ./main

2018-05-23  Hristian Kirtchev  <kirtchev@adacore.com>

gcc/ada/

	* exp_ch3.adb (Default_Initialize_Object): Do not optimize scalar array
	initialization when the component type has predicates.
	* exp_ch4.adb (Expand_N_Allocator): Do not optimize scalar array
	allocation when the component type has predicates.

From-SVN: r260572
This commit is contained in:
Hristian Kirtchev 2018-05-23 10:21:42 +00:00 committed by Pierre-Marie de Rodat
parent 3d58177769
commit 40016fa77f
3 changed files with 64 additions and 29 deletions

View file

@ -1,3 +1,10 @@
2018-05-23 Hristian Kirtchev <kirtchev@adacore.com>
* exp_ch3.adb (Default_Initialize_Object): Do not optimize scalar array
initialization when the component type has predicates.
* exp_ch4.adb (Expand_N_Allocator): Do not optimize scalar array
allocation when the component type has predicates.
2018-05-23 Hristian Kirtchev <kirtchev@adacore.com>
* einfo.adb, exp_disp.adb, sem_ch3.adb, sem_ch6.adb, sem_prag.adb:

View file

@ -6069,29 +6069,43 @@ package body Exp_Ch3 is
null;
-- Optimize the default initialization of an array object when
-- the following conditions are met:
--
-- * Pragma Initialize_Scalars or Normalize_Scalars is in
-- effect.
--
-- * The bounds of the array type are static and lack empty
-- ranges.
--
-- * The array type does not contain atomic components or is
-- treated as packed.
--
-- * The component is of a scalar type which requires simple
-- initialization.
--
-- pragma Initialize_Scalars or Normalize_Scalars is in effect.
-- Construct an in-place initialization aggregate which may be
-- convert into a fast memset by the backend.
elsif Init_Or_Norm_Scalars
and then Is_Array_Type (Typ)
-- The array must lack atomic components because they are
-- treated as non-static, and as a result the backend will
-- not initialize the memory in one go.
and then not Has_Atomic_Components (Typ)
-- The array must not be packed because the invalid values
-- in System.Scalar_Values are multiples of Storage_Unit.
and then not Is_Packed (Typ)
-- The array must have static non-empty ranges, otherwise
-- the backend cannot initialize the memory in one go.
and then Has_Static_Non_Empty_Array_Bounds (Typ)
-- The optimization is only relevant for arrays of scalar
-- types.
and then Is_Scalar_Type (Component_Type (Typ))
-- Similar to regular array initialization using a type
-- init proc, predicate checks are not performed because the
-- initialization values are intentionally invalid, and may
-- violate the predicate.
and then not Has_Predicates (Component_Type (Typ))
-- The component type must have a single initialization value
and then Simple_Initialization_OK (Component_Type (Typ))
then
Set_No_Initialization (N, False);

View file

@ -4618,28 +4618,42 @@ package body Exp_Ch4 is
Is_Allocate => True);
end if;
-- Optimize the default allocation of an array object when the
-- following conditions are met:
--
-- * Pragma Initialize_Scalars or Normalize_Scalars is in effect
--
-- * The bounds of the array type are static and lack empty ranges
--
-- * The array type does not contain atomic components or is
-- treated as packed.
--
-- * The component is of a scalar type which requires simple
-- initialization.
--
-- Construct an in-place initialization aggregate which may be
-- convert into a fast memset by the backend.
-- Optimize the default allocation of an array object when pragma
-- Initialize_Scalars or Normalize_Scalars is in effect. Construct an
-- in-place initialization aggregate which may be convert into a fast
-- memset by the backend.
elsif Init_Or_Norm_Scalars
and then Is_Array_Type (T)
-- The array must lack atomic components because they are treated
-- as non-static, and as a result the backend will not initialize
-- the memory in one go.
and then not Has_Atomic_Components (T)
-- The array must not be packed because the invalid values in
-- System.Scalar_Values are multiples of Storage_Unit.
and then not Is_Packed (T)
-- The array must have static non-empty ranges, otherwise the
-- backend cannot initialize the memory in one go.
and then Has_Static_Non_Empty_Array_Bounds (T)
-- The optimization is only relevant for arrays of scalar types
and then Is_Scalar_Type (Component_Type (T))
-- Similar to regular array initialization using a type init proc,
-- predicate checks are not performed because the initialization
-- values are intentionally invalid, and may violate the predicate.
and then not Has_Predicates (Component_Type (T))
-- The component type must have a single initialization value
and then Needs_Simple_Initialization
(Typ => Component_Type (T),
Consider_IS => True)