To compute the range of values in the generic actual Index_Type for a
vector, there is a series of compile-time tests to determine which of
Index_Type or Count_Type to use for intermediate values.

In the case of an Index_Type comprising a range of values larger than
in Count_Type, the number of values was computed using Index_Type, and
then converted to Count_Type. However, even though the computation of
the result does not overflow, the conversion of the result to type
Count_Type will fail when the value is greater than
Count_Type'Last. The solution is to first test whether the result is
less than Count_Type'Last, and only then convert the result.

Tested on x86_64-pc-linux-gnu, committed on trunk

2013-10-17  Matthew Heaney  <hea...@adacore.com>

        * a-convec.adb, a-coinve.adb, a-cobove.adb (Insert, Insert_Space):
        Inspect value range before converting type.

Index: a-coinve.adb
===================================================================
--- a-coinve.adb        (revision 203568)
+++ a-coinve.adb        (working copy)
@@ -1734,7 +1734,22 @@
             --  worry about if No_Index were less than 0, but that case is
             --  handled above).
 
-            Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            if Index_Type'Last - No_Index >=
+                 Count_Type'Pos (Count_Type'Last)
+            then
+               --  We have determined that range of Index_Type has at least as
+               --  many values as in Count_Type, so Count_Type'Last is the
+               --  maximum number of items that are allowed.
+
+               Max_Length := Count_Type'Last;
+
+            else
+               --  The range of Index_Type has fewer values than in Count_Type,
+               --  so the maximum number of items is computed from the range of
+               --  the Index_Type.
+
+               Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            end if;
          end if;
 
       elsif Index_Type'First <= 0 then
@@ -2504,7 +2519,22 @@
             --  worry about if No_Index were less than 0, but that case is
             --  handled above).
 
-            Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            if Index_Type'Last - No_Index >=
+                 Count_Type'Pos (Count_Type'Last)
+            then
+               --  We have determined that range of Index_Type has at least as
+               --  many values as in Count_Type, so Count_Type'Last is the
+               --  maximum number of items that are allowed.
+
+               Max_Length := Count_Type'Last;
+
+            else
+               --  The range of Index_Type has fewer values than in Count_Type,
+               --  so the maximum number of items is computed from the range of
+               --  the Index_Type.
+
+               Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            end if;
          end if;
 
       elsif Index_Type'First <= 0 then
Index: a-cobove.adb
===================================================================
--- a-cobove.adb        (revision 203568)
+++ a-cobove.adb        (working copy)
@@ -1227,7 +1227,22 @@
             --  worry about if No_Index were less than 0, but that case is
             --  handled above).
 
-            Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            if Index_Type'Last - No_Index >=
+                 Count_Type'Pos (Count_Type'Last)
+            then
+               --  We have determined that range of Index_Type has at least as
+               --  many values as in Count_Type, so Count_Type'Last is the
+               --  maximum number of items that are allowed.
+
+               Max_Length := Count_Type'Last;
+
+            else
+               --  The range of Index_Type has fewer values than in Count_Type,
+               --  so the maximum number of items is computed from the range of
+               --  the Index_Type.
+
+               Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            end if;
          end if;
 
       elsif Index_Type'First <= 0 then
@@ -1685,7 +1700,22 @@
             --  worry about if No_Index were less than 0, but that case is
             --  handled above).
 
-            Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            if Index_Type'Last - No_Index >=
+                 Count_Type'Pos (Count_Type'Last)
+            then
+               --  We have determined that range of Index_Type has at least as
+               --  many values as in Count_Type, so Count_Type'Last is the
+               --  maximum number of items that are allowed.
+
+               Max_Length := Count_Type'Last;
+
+            else
+               --  The range of Index_Type has fewer values than in Count_Type,
+               --  so the maximum number of items is computed from the range of
+               --  the Index_Type.
+
+               Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            end if;
          end if;
 
       elsif Index_Type'First <= 0 then
Index: a-convec.adb
===================================================================
--- a-convec.adb        (revision 203568)
+++ a-convec.adb        (working copy)
@@ -1386,7 +1386,22 @@
             --  worry about if No_Index were less than 0, but that case is
             --  handled above).
 
-            Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            if Index_Type'Last - No_Index >=
+                 Count_Type'Pos (Count_Type'Last)
+            then
+               --  We have determined that range of Index_Type has at least as
+               --  many values as in Count_Type, so Count_Type'Last is the
+               --  maximum number of items that are allowed.
+
+               Max_Length := Count_Type'Last;
+
+            else
+               --  The range of Index_Type has fewer values than in Count_Type,
+               --  so the maximum number of items is computed from the range of
+               --  the Index_Type.
+
+               Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            end if;
          end if;
 
       elsif Index_Type'First <= 0 then
@@ -2033,7 +2048,22 @@
             --  worry about if No_Index were less than 0, but that case is
             --  handled above).
 
-            Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            if Index_Type'Last - No_Index >=
+                 Count_Type'Pos (Count_Type'Last)
+            then
+               --  We have determined that range of Index_Type has at least as
+               --  many values as in Count_Type, so Count_Type'Last is the
+               --  maximum number of items that are allowed.
+
+               Max_Length := Count_Type'Last;
+
+            else
+               --  The range of Index_Type has fewer values than in Count_Type,
+               --  so the maximum number of items is computed from the range of
+               --  the Index_Type.
+
+               Max_Length := Count_Type'Base (Index_Type'Last - No_Index);
+            end if;
          end if;
 
       elsif Index_Type'First <= 0 then

Reply via email to