Commit d21ae867 by Bob Duff Committed by Pierre-Marie de Rodat

[Ada] Warn on Unchecked_Conversion to zero-sized array

The compiler usually warns on Unchecked_Conversion between types with
mismatched sizes. This warning is now extended to the case where the
target type is a zero-sized array.

2019-08-20  Bob Duff  <duff@adacore.com>

gcc/ada/

	* sem_ch13.adb (Is_Null_Array): New function, used to detect the
	null array case; used to warn about uncheckedly converting to a
	zero-sized array.  It is unfortunate that we can't just check
	the size, and warn on all cases of converting from a
	nonzero-sized type to a zero-sized one. That's because "0" means
	two different things: "size is zero" and "size is unknown".
	Until we fix that design flaw, we need this more targeted fix.

gcc/testsuite/

	* gnat.dg/unchecked_convert14.adb: New testcase.

From-SVN: r274725
parent cbdb0df1
2019-08-20 Bob Duff <duff@adacore.com> 2019-08-20 Bob Duff <duff@adacore.com>
* sem_ch13.adb (Is_Null_Array): New function, used to detect the
null array case; used to warn about uncheckedly converting to a
zero-sized array. It is unfortunate that we can't just check
the size, and warn on all cases of converting from a
nonzero-sized type to a zero-sized one. That's because "0" means
two different things: "size is zero" and "size is unknown".
Until we fix that design flaw, we need this more targeted fix.
2019-08-20 Bob Duff <duff@adacore.com>
* libgnat/a-cborma.adb, libgnat/a-cborse.adb (Clear): Repeatedly * libgnat/a-cborma.adb, libgnat/a-cborse.adb (Clear): Repeatedly
call Delete. This avoids clearing the free list, which call Delete. This avoids clearing the free list, which
substantially speeds up future Delete operations. substantially speeds up future Delete operations.
......
...@@ -14625,6 +14625,39 @@ package body Sem_Ch13 is ...@@ -14625,6 +14625,39 @@ package body Sem_Ch13 is
------------------------------------ ------------------------------------
procedure Validate_Unchecked_Conversions is procedure Validate_Unchecked_Conversions is
function Is_Null_Array (T : Entity_Id) return Boolean;
-- We want to warn in the case of converting to a wrong-sized array of
-- bytes, including the zero-size case. This returns True in that case,
-- which is necessary because a size of 0 is used to indicate both an
-- unknown size and a size of 0. It's OK for this to return True in
-- other zero-size cases, but we don't go out of our way; for example,
-- we don't bother with multidimensional arrays.
function Is_Null_Array (T : Entity_Id) return Boolean is
begin
if Is_Array_Type (T) and then Is_Constrained (T) then
declare
Index : constant Node_Id := First_Index (T);
R : Node_Id; -- N_Range
begin
case Nkind (Index) is
when N_Range =>
R := Index;
when N_Subtype_Indication =>
R := Range_Expression (Constraint (Index));
when N_Identifier | N_Expanded_Name =>
R := Scalar_Range (Entity (Index));
when others =>
raise Program_Error;
end case;
return Is_Null_Range (Low_Bound (R), High_Bound (R));
end;
end if;
return False;
end Is_Null_Array;
begin begin
for N in Unchecked_Conversions.First .. Unchecked_Conversions.Last loop for N in Unchecked_Conversions.First .. Unchecked_Conversions.Last loop
declare declare
...@@ -14641,28 +14674,28 @@ package body Sem_Ch13 is ...@@ -14641,28 +14674,28 @@ package body Sem_Ch13 is
begin begin
-- Skip if function marked as warnings off -- Skip if function marked as warnings off
if Warnings_Off (Act_Unit) then if Warnings_Off (Act_Unit) or else Serious_Errors_Detected > 0 then
goto Continue; goto Continue;
end if; end if;
-- This validation check, which warns if we have unequal sizes for
-- unchecked conversion, and thus potentially implementation
-- dependent semantics, is one of the few occasions on which we
-- use the official RM size instead of Esize. See description in
-- Einfo "Handling of Type'Size Values" for details.
if Serious_Errors_Detected = 0
and then Known_Static_RM_Size (Source)
and then Known_Static_RM_Size (Target)
-- Don't do the check if warnings off for either type, note the -- Don't do the check if warnings off for either type, note the
-- deliberate use of OR here instead of OR ELSE to get the flag -- deliberate use of OR here instead of OR ELSE to get the flag
-- Warnings_Off_Used set for both types if appropriate. -- Warnings_Off_Used set for both types if appropriate.
and then not (Has_Warnings_Off (Source) if Has_Warnings_Off (Source) or Has_Warnings_Off (Target) then
or goto Continue;
Has_Warnings_Off (Target)) end if;
if (Known_Static_RM_Size (Source)
and then Known_Static_RM_Size (Target))
or else Is_Null_Array (Target)
then then
-- This validation check, which warns if we have unequal sizes
-- for unchecked conversion, and thus implementation dependent
-- semantics, is one of the few occasions on which we use the
-- official RM size instead of Esize. See description in Einfo
-- "Handling of Type'Size Values" for details.
Source_Siz := RM_Size (Source); Source_Siz := RM_Size (Source);
Target_Siz := RM_Size (Target); Target_Siz := RM_Size (Target);
......
2019-08-20 Bob Duff <duff@adacore.com> 2019-08-20 Bob Duff <duff@adacore.com>
* gnat.dg/unchecked_convert14.adb: New testcase.
2019-08-20 Bob Duff <duff@adacore.com>
* gnat.dg/object_size1.adb: New testcase. * gnat.dg/object_size1.adb: New testcase.
2019-08-20 Eric Botcazou <ebotcazou@adacore.com> 2019-08-20 Eric Botcazou <ebotcazou@adacore.com>
......
-- { dg-do compile }
with Ada.Unchecked_Conversion;
with System.Storage_Elements; use System.Storage_Elements;
procedure Unchecked_Convert14 is
type R is record
I : Integer;
C : Character;
end record;
subtype Buffer is Storage_Array (1 .. 0);
function As_Buffer is new Ada.Unchecked_Conversion -- { dg-warning "types for unchecked conversion have different sizes" }
(Source => R, Target => Buffer);
type Buffer_1 is array (Storage_Offset range 1 .. 1) of Storage_Element;
function As_Buffer_1 is new Ada.Unchecked_Conversion -- { dg-warning "types for unchecked conversion have different sizes" }
(Source => R, Target => Buffer_1);
B : Buffer;
B_1 : Buffer_1;
My_R : R := (1, 'x');
begin
B := As_Buffer (My_R);
B_1 := As_Buffer_1 (My_R);
end Unchecked_Convert14;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment