diff mbox

[Ada] Make sure we check divide by zero for fixed-point divide case

Message ID 20150106091055.GA5818@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Jan. 6, 2015, 9:10 a.m. UTC
On some targets, the compiler does not generate a required divide by
zero check for the case of fixed-point operands. This was noticed in
the context of the second division function in Ada.Real_Time, but is
a quite general problem. The following program:

     1. function DivCTest return Duration is
     2.    type Time_Span is new Duration;
     3.    function f (X : Time_Span; Y : Integer) return Time_Span is
     4.       pragma Unsuppress (Overflow_Check);
     5.       pragma Unsuppress (Division_Check);
     6.    begin
     7.       return Time_Span (Duration (X) / Y);
     8.    end;
     9. begin
    10.    return Duration (f (10.0, 0));
    11. end;

should generate an exception on all targets. On native platforms
the output will be:

raised CONSTRAINT_ERROR : divctest.adb:6 divide by zero

Note: on some targets notably Windows, this message is obtained
without this fix, since the back end can in fact correctly handle
the generated division by zero, but this is not true on all targets.

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

2015-01-06  Robert Dewar  <dewar@adacore.com>

	* exp_ch4.adb (Expand_N_Op_Divide): Generate explicit divide by
	zero check for fixed-point case if Backend_Divide_Checks_On_Target
	is False.
diff mbox

Patch

Index: exp_ch4.adb
===================================================================
--- exp_ch4.adb	(revision 219191)
+++ exp_ch4.adb	(working copy)
@@ -6701,6 +6701,26 @@ 
 
       if Is_Fixed_Point_Type (Typ) then
 
+         --  Deal with divide-by-zero check if back end cannot handle them
+         --  and the flag is set indicating that we need such a check. Note
+         --  that we don't need to bother here with the case of mixed-mode
+         --  (Right operand an integer type), since these will be rewritten
+         --  with conversions to a divide with a fixed-point right operand.
+
+         if Do_Division_Check (N)
+           and then not Backend_Divide_Checks_On_Target
+           and then not Is_Integer_Type (Rtyp)
+         then
+            Set_Do_Division_Check (N, False);
+            Insert_Action (N,
+              Make_Raise_Constraint_Error (Loc,
+                Condition =>
+                  Make_Op_Eq (Loc,
+                    Left_Opnd  => Duplicate_Subexpr_Move_Checks (Ropnd),
+                    Right_Opnd => Make_Real_Literal (Loc, Ureal_0)),
+                  Reason  => CE_Divide_By_Zero));
+         end if;
+
          --  No special processing if Treat_Fixed_As_Integer is set, since
          --  from a semantic point of view such operations are simply integer
          --  operations and will be treated that way.