From d21ae867a5a83c7c5dd11a2e51d0c4b2ff9e41b8 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Tue, 20 Aug 2019 09:49:12 +0000 Subject: [PATCH] [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 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 --- gcc/ada/ChangeLog | 10 +++ gcc/ada/sem_ch13.adb | 65 ++++++++++++++----- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gnat.dg/unchecked_convert14.adb | 30 +++++++++ 4 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/unchecked_convert14.adb diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f8f43c00441..8ab2eddd646 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,13 @@ +2019-08-20 Bob Duff + + * 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 * libgnat/a-cborma.adb, libgnat/a-cborse.adb (Clear): Repeatedly diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 415687922df..2538c1da982 100644 --- a/gcc/ada/sem_ch13.adb +++ b/gcc/ada/sem_ch13.adb @@ -14625,6 +14625,39 @@ package body Sem_Ch13 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 for N in Unchecked_Conversions.First .. Unchecked_Conversions.Last loop declare @@ -14641,28 +14674,28 @@ package body Sem_Ch13 is begin -- 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; 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 + -- deliberate use of OR here instead of OR ELSE to get the flag + -- Warnings_Off_Used set for both types if appropriate. - -- 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 - -- Warnings_Off_Used set for both types if appropriate. + if Has_Warnings_Off (Source) or Has_Warnings_Off (Target) then + goto Continue; + end if; - and then not (Has_Warnings_Off (Source) - or - Has_Warnings_Off (Target)) + if (Known_Static_RM_Size (Source) + and then Known_Static_RM_Size (Target)) + or else Is_Null_Array (Target) 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); Target_Siz := RM_Size (Target); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 89406642e92..61e37dad25b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-08-20 Bob Duff + + * gnat.dg/unchecked_convert14.adb: New testcase. + 2019-08-20 Bob Duff * gnat.dg/object_size1.adb: New testcase. diff --git a/gcc/testsuite/gnat.dg/unchecked_convert14.adb b/gcc/testsuite/gnat.dg/unchecked_convert14.adb new file mode 100644 index 00000000000..756d8366d78 --- /dev/null +++ b/gcc/testsuite/gnat.dg/unchecked_convert14.adb @@ -0,0 +1,30 @@ +-- { 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; -- 2.30.2