aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Duff <duff@adacore.com>2019-08-20 09:49:12 +0000
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>2019-08-20 09:49:12 +0000
commitd21ae867a5a83c7c5dd11a2e51d0c4b2ff9e41b8 (patch)
tree5b8faed21ae8afa0d01919098dd50a21ea2cb429
parentcbdb0df117deb12a8e7d63e1cf2b53415b8e92e2 (diff)
downloadgcc-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/ChangeLog10
-rw-r--r--gcc/ada/sem_ch13.adb65
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gnat.dg/unchecked_convert14.adb30
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;