diff options
author | Bob Duff <duff@adacore.com> | 2019-08-20 09:49:12 +0000 |
---|---|---|
committer | Pierre-Marie de Rodat <pmderodat@gcc.gnu.org> | 2019-08-20 09:49:12 +0000 |
commit | d21ae867a5a83c7c5dd11a2e51d0c4b2ff9e41b8 (patch) | |
tree | 5b8faed21ae8afa0d01919098dd50a21ea2cb429 | |
parent | cbdb0df117deb12a8e7d63e1cf2b53415b8e92e2 (diff) | |
download | gcc-d21ae867a5a83c7c5dd11a2e51d0c4b2ff9e41b8.zip gcc-d21ae867a5a83c7c5dd11a2e51d0c4b2ff9e41b8.tar.gz gcc-d21ae867a5a83c7c5dd11a2e51d0c4b2ff9e41b8.tar.bz2 |
[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
-rw-r--r-- | gcc/ada/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/ada/sem_ch13.adb | 65 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/unchecked_convert14.adb | 30 |
4 files changed, 93 insertions, 16 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index f8f43c0..8ab2edd 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,15 @@ 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 call Delete. This avoids clearing the free list, which substantially speeds up future Delete operations. diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb index 4156879..2538c1d 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 8940664..61e37da 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 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. 2019-08-20 Eric Botcazou <ebotcazou@adacore.com> diff --git a/gcc/testsuite/gnat.dg/unchecked_convert14.adb b/gcc/testsuite/gnat.dg/unchecked_convert14.adb new file mode 100644 index 0000000..756d836 --- /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; |