[Ada] Avoid uninitialized variable in bounded containers
authorBob Duff <duff@adacore.com>
Wed, 18 Sep 2019 08:31:37 +0000 (08:31 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Wed, 18 Sep 2019 08:31:37 +0000 (08:31 +0000)
In function Copy in Ada.Containers.Bounded_Ordered_Sets and other
bounded containers packages, remove a possible use of an uninitialized
variable. This was not a bug, because the uninitialized variable could
be used only if checks are suppressed, and the checks would have failed,
leading to erroneous execution.

However, it seems more robust this way, and is probably equally
efficient, and avoids a warning that is given if checks are suppressed,
and the -Wall switch is given, and optimization is turned on.

2019-09-18  Bob Duff  <duff@adacore.com>

gcc/ada/

* libgnat/a-cbhama.adb, libgnat/a-cbhase.adb,
libgnat/a-cbmutr.adb, libgnat/a-cborma.adb,
libgnat/a-cborse.adb, libgnat/a-cobove.adb (Copy): Avoid reading
the uninitialized variable C in the Checks = False case. Change
variable to be a constant.

gcc/testsuite/

* gnat.dg/containers1.adb, gnat.dg/containers1.ads: New
testcase.

From-SVN: r275839

gcc/ada/ChangeLog
gcc/ada/libgnat/a-cbhama.adb
gcc/ada/libgnat/a-cbhase.adb
gcc/ada/libgnat/a-cbmutr.adb
gcc/ada/libgnat/a-cborma.adb
gcc/ada/libgnat/a-cborse.adb
gcc/ada/libgnat/a-cobove.adb
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/containers1.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/containers1.ads [new file with mode: 0644]

index 8906ea1b537a835a89f28f5aa342488c1a114e6e..d4c51d102d7783b3dfdb3139bf5699b5170fabb4 100644 (file)
@@ -1,3 +1,11 @@
+2019-09-18  Bob Duff  <duff@adacore.com>
+
+       * libgnat/a-cbhama.adb, libgnat/a-cbhase.adb,
+       libgnat/a-cbmutr.adb, libgnat/a-cborma.adb,
+       libgnat/a-cborse.adb, libgnat/a-cobove.adb (Copy): Avoid reading
+       the uninitialized variable C in the Checks = False case. Change
+       variable to be a constant.
+
 2019-09-18  Claire Dross  <dross@adacore.com>
 
        * libgnat/a-cofuma.adb (Remove, Elements_Equal_Except,
index 68e3602d87984e26720574a1b6d881d9963945cf..74e3d95748a6222470407ecab18163d983204bb3 100644 (file)
@@ -262,18 +262,14 @@ package body Ada.Containers.Bounded_Hashed_Maps is
       Capacity : Count_Type := 0;
       Modulus  : Hash_Type := 0) return Map
    is
-      C : Count_Type;
+      C : constant Count_Type :=
+        (if Capacity = 0 then Source.Length
+         else Capacity);
       M : Hash_Type;
 
    begin
-      if Capacity = 0 then
-         C := Source.Length;
-
-      elsif Capacity >= Source.Length then
-         C := Capacity;
-
-      elsif Checks then
-         raise Capacity_Error with "Capacity value too small";
+      if Checks and then C < Source.Length then
+         raise Capacity_Error with "Capacity too small";
       end if;
 
       if Modulus = 0 then
index 796cb9714210b03dde6160a8f7e9fb5547eeddc5..390e82bb48543f006178c4075daa87956fc72591 100644 (file)
@@ -254,16 +254,14 @@ package body Ada.Containers.Bounded_Hashed_Sets is
       Capacity : Count_Type := 0;
       Modulus  : Hash_Type := 0) return Set
    is
-      C : Count_Type;
+      C : constant Count_Type :=
+        (if Capacity = 0 then Source.Length
+         else Capacity);
       M : Hash_Type;
 
    begin
-      if Capacity = 0 then
-         C := Source.Length;
-      elsif Capacity >= Source.Length then
-         C := Capacity;
-      elsif Checks then
-         raise Capacity_Error with "Capacity value too small";
+      if Checks and then C < Source.Length then
+         raise Capacity_Error with "Capacity too small";
       end if;
 
       if Modulus = 0 then
index fb8585a100f4ca1dd21b2dfa630357261302cc12..4c0f8fe1c297ae0d1ab1269e7b7c3cadb8472992 100644 (file)
@@ -625,15 +625,12 @@ package body Ada.Containers.Bounded_Multiway_Trees is
      (Source   : Tree;
       Capacity : Count_Type := 0) return Tree
    is
-      C : Count_Type;
-
+      C : constant Count_Type :=
+        (if Capacity = 0 then Source.Count
+         else Capacity);
    begin
-      if Capacity = 0 then
-         C := Source.Count;
-      elsif Capacity >= Source.Count then
-         C := Capacity;
-      elsif Checks then
-         raise Capacity_Error with "Capacity value too small";
+      if Checks and then C < Source.Count then
+         raise Capacity_Error with "Capacity too small";
       end if;
 
       return Target : Tree (Capacity => C) do
index 55be7ad0327882b2f661863f647aeae907d0d05a..e4e4b57dc7282e1e86eb9ed7911611b8dcef18ee 100644 (file)
@@ -464,17 +464,12 @@ package body Ada.Containers.Bounded_Ordered_Maps is
    ----------
 
    function Copy (Source : Map; Capacity : Count_Type := 0) return Map is
-      C : Count_Type;
-
+      C : constant Count_Type :=
+        (if Capacity = 0 then Source.Length
+         else Capacity);
    begin
-      if Capacity = 0 then
-         C := Source.Length;
-
-      elsif Capacity >= Source.Length then
-         C := Capacity;
-
-      elsif Checks then
-         raise Capacity_Error with "Capacity value too small";
+      if Checks and then C < Source.Length then
+         raise Capacity_Error with "Capacity too small";
       end if;
 
       return Target : Map (Capacity => C) do
index 9fdba269d2813ce7a6d28ac784cba762cb4ac1d0..7b983781e60b0dbf431f7d32f436ee496ecad678 100644 (file)
@@ -442,15 +442,12 @@ package body Ada.Containers.Bounded_Ordered_Sets is
    ----------
 
    function Copy (Source : Set; Capacity : Count_Type := 0) return Set is
-      C : Count_Type;
-
+      C : constant Count_Type :=
+        (if Capacity = 0 then Source.Length
+         else Capacity);
    begin
-      if Capacity = 0 then
-         C := Source.Length;
-      elsif Capacity >= Source.Length then
-         C := Capacity;
-      elsif Checks then
-         raise Capacity_Error with "Capacity value too small";
+      if Checks and then C < Source.Length then
+         raise Capacity_Error with "Capacity too small";
       end if;
 
       return Target : Set (Capacity => C) do
index 8d80fb70323dbfae7a8ea71d82601dc503256589..3e48bc60e8ab6ba412f9a7e19a69aa6f74dcf8c9 100644 (file)
@@ -451,18 +451,12 @@ package body Ada.Containers.Bounded_Vectors is
      (Source   : Vector;
       Capacity : Count_Type := 0) return Vector
    is
-      C : Count_Type;
-
+      C : constant Count_Type :=
+        (if Capacity = 0 then Source.Length
+         else Capacity);
    begin
-      if Capacity = 0 then
-         C := Source.Length;
-
-      elsif Capacity >= Source.Length then
-         C := Capacity;
-
-      elsif Checks then
-         raise Capacity_Error
-           with "Requested capacity is less than Source length";
+      if Checks and then C < Source.Length then
+         raise Capacity_Error with "Capacity too small";
       end if;
 
       return Target : Vector (C) do
index cc27ca318c222cbf6870f3ef63f692906d356bab..5e143b57456799b1c23bf29a734cd1e6701308d4 100644 (file)
@@ -1,3 +1,8 @@
+2019-09-18  Bob Duff  <duff@adacore.com>
+
+       * gnat.dg/containers1.adb, gnat.dg/containers1.ads: New
+       testcase.
+
 2019-09-18  Richard Sandiford  <richard.sandiford@arm.com>
 
        * gcc.target/i386/pr82361-1.c (f1, f2, f3, f4, f5, f6): Force
diff --git a/gcc/testsuite/gnat.dg/containers1.adb b/gcc/testsuite/gnat.dg/containers1.adb
new file mode 100644 (file)
index 0000000..47ac655
--- /dev/null
@@ -0,0 +1,5 @@
+--  { dg-do compile }
+--  { dg-options "-Wall -O2" }
+package body Containers1 is
+   procedure Dummy is null;
+end Containers1;
diff --git a/gcc/testsuite/gnat.dg/containers1.ads b/gcc/testsuite/gnat.dg/containers1.ads
new file mode 100644 (file)
index 0000000..3c1fd89
--- /dev/null
@@ -0,0 +1,6 @@
+with Ada.Containers.Bounded_Ordered_Sets; use Ada.Containers;
+package Containers1 is
+   pragma Suppress (All_Checks);
+   package Sets is new Bounded_Ordered_Sets (Boolean);
+   procedure Dummy;
+end Containers1;
\ No newline at end of file