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