This patch removes an old range check optimization which incorrectly assumes that the type of an arbitrary expression can always fit in the target type of a conversion.
------------ -- Source -- ------------ -- main.adb with Interfaces; use Interfaces; procedure Main is subtype Small_Positive is Integer_16 range 1 .. Integer_16'Last; type Target_Typ is array (Small_Positive range <>) of Boolean; pragma Convention (C, Target_Typ); subtype Large_Positive is Integer_32 range 1 .. 60_000; type Expr_Typ is array (Large_Positive range <>) of Boolean; type Expr_Typ_Ptr is access Expr_Typ; Expr : constant Expr_Typ := (1 .. 60_000 => True); Expr_Ptr : constant Expr_Typ_Ptr := new Expr_Typ'(Expr); Target : constant Target_Typ := Target_Typ (Expr_Ptr.all); begin null; end Main; ---------------------------- -- Compilation and output -- ---------------------------- $ gnatmake -q main.adb $ ./main.adb raised CONSTRAINT_ERROR : main.adb:16 range check failed Tested on x86_64-pc-linux-gnu, committed on trunk 2012-08-06 Hristian Kirtchev <kirtc...@adacore.com> * checks.adb (Discrete_Range_Cond): Do not try to optimize on the assumption that the type of an expression can always fit in the target type of a conversion.
Index: checks.adb =================================================================== --- checks.adb (revision 190155) +++ checks.adb (working copy) @@ -6660,12 +6660,6 @@ LB := New_Occurrence_Of (Discriminal (Entity (LB)), Loc); end if; - if Nkind (HB) = N_Identifier - and then Ekind (Entity (HB)) = E_Discriminant - then - HB := New_Occurrence_Of (Discriminal (Entity (HB)), Loc); - end if; - Left_Opnd := Make_Op_Lt (Loc, Left_Opnd => @@ -6677,28 +6671,10 @@ (Base_Type (Typ), Get_E_First_Or_Last (Loc, Typ, 0, Name_First))); - if Base_Type (Typ) = Typ then - return Left_Opnd; - - elsif Compile_Time_Known_Value (High_Bound (Scalar_Range (Typ))) - and then - Compile_Time_Known_Value (High_Bound (Scalar_Range - (Base_Type (Typ)))) + if Nkind (HB) = N_Identifier + and then Ekind (Entity (HB)) = E_Discriminant then - if Is_Floating_Point_Type (Typ) then - if Expr_Value_R (High_Bound (Scalar_Range (Typ))) = - Expr_Value_R (High_Bound (Scalar_Range (Base_Type (Typ)))) - then - return Left_Opnd; - end if; - - else - if Expr_Value (High_Bound (Scalar_Range (Typ))) = - Expr_Value (High_Bound (Scalar_Range (Base_Type (Typ)))) - then - return Left_Opnd; - end if; - end if; + HB := New_Occurrence_Of (Discriminal (Entity (HB)), Loc); end if; Right_Opnd :=