diff mbox

[Ada] Handle constraint error in vector when large index type

Message ID 20131017134631.GA14569@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Oct. 17, 2013, 1:46 p.m. UTC
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  <heaney@adacore.com>

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

Patch

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