checks.adb (Apply_Arithmetic_Overflow_Checked_Suppressed): New name for Apply_Arithme...
authorRobert Dewar <dewar@adacore.com>
Tue, 2 Oct 2012 08:37:54 +0000 (08:37 +0000)
committerArnaud Charlet <charlet@gcc.gnu.org>
Tue, 2 Oct 2012 08:37:54 +0000 (10:37 +0200)
2012-10-02  Robert Dewar  <dewar@adacore.com>

* checks.adb (Apply_Arithmetic_Overflow_Checked_Suppressed):
New name for Apply_Arithmetic_Overflow_Normal
(Apply_Arithmetic_Overflow_Minimized_Eliminated):
Add handling for conditional expressions
(Is_Signed_Integer_Arithmetic_Op): Now includes conditional
expressions (Minimize_Eliminate_Overflow_Checks): Handle
conditional expressions.
* checks.ads: Minor comment fixes.
* exp_ch4.adb (Expand_N_Case_Expression): Call
Apply_Arithmetic_Overflow_Check (Expand_N_Conditional_Expression):
Call Apply_Arithmetic_Overflow_Check
* s-bignum.adb (Normalize): Remove incorrect precondition.
* sem_res.adb (Resolve_Case_Expression): Set Do_Overflow_Check
flag (Resolve_Conditional_Expression): Set Do_Overflow_Check flag.
* sinfo.adb: Add Do_Overflow_Check for conditional expressions.
* sinfo.ads: Minor documentation updates.

From-SVN: r191964

gcc/ada/ChangeLog
gcc/ada/checks.adb
gcc/ada/checks.ads
gcc/ada/exp_ch4.adb
gcc/ada/s-bignum.adb
gcc/ada/sem_res.adb
gcc/ada/sinfo.adb
gcc/ada/sinfo.ads

index 63401fbc962f4d74c05bb593872ea0070c2f15a5..8dd037ffba443b74545c5b62e377c4811c1c6c27 100644 (file)
@@ -1,3 +1,22 @@
+2012-10-02  Robert Dewar  <dewar@adacore.com>
+
+       * checks.adb (Apply_Arithmetic_Overflow_Checked_Suppressed):
+       New name for Apply_Arithmetic_Overflow_Normal
+       (Apply_Arithmetic_Overflow_Minimized_Eliminated):
+       Add handling for conditional expressions
+       (Is_Signed_Integer_Arithmetic_Op): Now includes conditional
+       expressions (Minimize_Eliminate_Overflow_Checks): Handle
+       conditional expressions.
+       * checks.ads: Minor comment fixes.
+       * exp_ch4.adb (Expand_N_Case_Expression): Call
+       Apply_Arithmetic_Overflow_Check (Expand_N_Conditional_Expression):
+       Call Apply_Arithmetic_Overflow_Check
+       * s-bignum.adb (Normalize): Remove incorrect precondition.
+       * sem_res.adb (Resolve_Case_Expression): Set Do_Overflow_Check
+       flag (Resolve_Conditional_Expression): Set Do_Overflow_Check flag.
+       * sinfo.adb: Add Do_Overflow_Check for conditional expressions.
+       * sinfo.ads: Minor documentation updates.
+
 2012-10-02  Ed Schonberg  <schonberg@adacore.com>
 
        * exp_ch4.adb (Expand_N_Case_Expression): Do not introduce
index f7be38350155350ab767da0ebe57246d79b56b2f..da2029288d9d7328cb1d488d337d028cb2576893 100644 (file)
@@ -193,15 +193,17 @@ package body Checks is
    -- Local Subprograms --
    -----------------------
 
-   procedure Apply_Arithmetic_Overflow_Normal (N : Node_Id);
+   procedure Apply_Arithmetic_Overflow_Checked_Suppressed (N : Node_Id);
    --  Used to apply arithmetic overflow checks for all cases except operators
    --  on signed arithmetic types in Minimized/Eliminate case (for which we
-   --  call Apply_Arithmetic_Overflow_Minimized_Eliminated below).
+   --  call Apply_Arithmetic_Overflow_Minimized_Eliminated below). N is always
+   --  a signed integer arithmetic operator (conditional expression excluded).
 
    procedure Apply_Arithmetic_Overflow_Minimized_Eliminated (Op : Node_Id);
    --  Used to apply arithmetic overflow checks for the case where the overflow
    --  checking mode is Minimized or Eliminated (and the Do_Overflow_Check flag
-   --  is known to be set) and we have an signed integer arithmetic op.
+   --  is known to be set) and we have an signed integer arithmetic op (which
+   --  includes the case of conditional expressions).
 
    procedure Apply_Division_Check
      (N   : Node_Id;
@@ -311,8 +313,10 @@ package body Checks is
 
    function Is_Signed_Integer_Arithmetic_Op (N : Node_Id) return Boolean;
    --  Returns True if node N is for an arithmetic operation with signed
-   --  integer operands. This is the kind of node for which special handling
-   --  applies in MINIMIZED or EXTENDED overflow checking mode.
+   --  integer operands. This includes unary and binary operators, and also
+   --  if and case expression nodes where the dependent expressions are of
+   --  a signed integer type. These are the kinds of nodes for which special
+   --  handling applies in MINIMIZED or EXTENDED overflow checking mode.
 
    function Range_Or_Validity_Checks_Suppressed
      (Expr : Node_Id) return Boolean;
@@ -767,7 +771,7 @@ package body Checks is
         or else not Do_Overflow_Check (N)
         or else not Is_Signed_Integer_Arithmetic_Op (N)
       then
-         Apply_Arithmetic_Overflow_Normal (N);
+         Apply_Arithmetic_Overflow_Checked_Suppressed (N);
 
       --  Otherwise use the new routine for Minimized/Eliminated modes for
       --  the case of a signed integer arithmetic op, with Do_Overflow_Check
@@ -778,9 +782,9 @@ package body Checks is
       end if;
    end Apply_Arithmetic_Overflow_Check;
 
-   --------------------------------------
-   -- Apply_Arithmetic_Overflow_Normal --
-   --------------------------------------
+   --------------------------------------------------
+   -- Apply_Arithmetic_Overflow_Checked_Suppressed --
+   --------------------------------------------------
 
    --  This routine is called only if the type is an integer type, and a
    --  software arithmetic overflow check may be needed for op (add, subtract,
@@ -798,7 +802,7 @@ package body Checks is
    --  Note: we also call this routine if we decide in the MINIMIZED case
    --  to give up and just generate an overflow check without any fuss.
 
-   procedure Apply_Arithmetic_Overflow_Normal (N : Node_Id) is
+   procedure Apply_Arithmetic_Overflow_Checked_Suppressed (N : Node_Id) is
       Loc   : constant Source_Ptr := Sloc (N);
       Typ   : constant Entity_Id  := Etype (N);
       Rtyp  : constant Entity_Id  := Root_Type (Typ);
@@ -1061,7 +1065,7 @@ package body Checks is
          when RE_Not_Available =>
             return;
       end;
-   end Apply_Arithmetic_Overflow_Normal;
+   end Apply_Arithmetic_Overflow_Checked_Suppressed;
 
    ----------------------------------------------------
    -- Apply_Arithmetic_Overflow_Minimized_Eliminated --
@@ -1081,7 +1085,7 @@ package body Checks is
       --  Original result type
 
       Check_Mode : constant Overflow_Check_Type :=
-        Overflow_Check_Mode (Etype (Op));
+                     Overflow_Check_Mode (Etype (Op));
       pragma Assert (Check_Mode in Minimized_Or_Eliminated);
 
       Lo, Hi : Uint;
@@ -1090,7 +1094,7 @@ package body Checks is
    begin
       --  Nothing to do if our parent is one of the following:
 
-      --    Another signed integer arithmetic operation
+      --    Another signed integer arithmetic op
       --    A membership operation
       --    A comparison operation
 
@@ -1111,7 +1115,7 @@ package body Checks is
          return;
       end if;
 
-      --  Otherwise, we have a top level arithmetic operator node, and this
+      --  Otherwise, we have a top level arithmetic operation node, and this
       --  is where we commence the special processing for minimize/eliminate.
       --  This is the case where we tell the machinery not to move into Bignum
       --  mode at this top level (of course the top level operation will still
@@ -3799,7 +3803,7 @@ package body Checks is
       Loc : constant Source_Ptr := Sloc (N);
 
    begin
-      --  Nothing to do if Bignum already
+      --  Nothing to do if Bignum already except call Relocate_Node
 
       if Is_RTE (Etype (N), RE_Bignum) then
          return Relocate_Node (N);
@@ -6254,6 +6258,13 @@ package body Checks is
               N_Op_Rem   | N_Op_Subtract =>
             return Is_Signed_Integer_Type (Etype (N));
 
+         when N_Conditional_Expression |
+              N_Case_Expression        =>
+            return Is_Signed_Integer_Type (Etype (N));
+
+         when N_Case_Expression_Alternative =>
+            return Is_Signed_Integer_Type (Etype (Parent (N)));
+
          when others =>
             return False;
       end case;
@@ -6677,7 +6688,9 @@ package body Checks is
       Hi        : out Uint;
       Top_Level : Boolean)
    is
-      pragma Assert (Is_Signed_Integer_Type (Etype (N)));
+      Rtyp : constant Entity_Id := Etype (N);
+      pragma Assert (Is_Signed_Integer_Type (Rtyp));
+      --  Result type, must be a signed integer type
 
       Check_Mode : constant Overflow_Check_Type := Overflow_Check_Mode (Empty);
       pragma Assert (Check_Mode in Minimized_Or_Eliminated);
@@ -6685,15 +6698,16 @@ package body Checks is
       Loc : constant Source_Ptr := Sloc (N);
 
       Rlo, Rhi : Uint;
-      --  Ranges of values for right operand
+      --  Ranges of values for right operand (operator case)
 
       Llo, Lhi : Uint;
-      --  Ranges of values for left operand
+      --  Ranges of values for left operand (operator case)
 
       LLIB : constant Entity_Id := Base_Type (Standard_Long_Long_Integer);
       --  Operands and results are of this type when we convert
 
-      LLLo, LLHi : Uint;
+      LLLo : constant Uint := Intval (Type_Low_Bound  (LLIB));
+      LLHi : constant Uint := Intval (Type_High_Bound (LLIB));
       --  Bounds of Long_Long_Integer
 
       Binary : constant Boolean := Nkind (N) in N_Binary_Op;
@@ -6705,7 +6719,17 @@ package body Checks is
       Bignum_Operands : Boolean;
       --  Set True if one or more operands is already of type Bignum, meaning
       --  that for sure (regardless of Top_Level setting) we are committed to
-      --  doing the operation in Bignum mode.
+      --  doing the operation in Bignum mode (or in the case of a case or if
+      --  expression, converting all the dependent expressions to bignum).
+
+      Long_Long_Integer_Operands : Boolean;
+      --  Set True if one r more operands is already of type Long_Loong_Integer
+      --  which means that if the result is known to be in the result type
+      --  range, then we must convert such operands back to the result type.
+      --  This switch is properly set only when Bignum_Operands is False.
+
+      function In_Result_Range return Boolean;
+      --  Returns True iff Lo .. Hi are within range of the result type
 
       procedure Max (A : in out Uint; B : Uint);
       --  If A is No_Uint, sets A to B, else to UI_Max (A, B);
@@ -6713,6 +6737,23 @@ package body Checks is
       procedure Min (A : in out Uint; B : Uint);
       --  If A is No_Uint, sets A to B, else to UI_Min (A, B);
 
+      ---------------------
+      -- In_Result_Range --
+      ---------------------
+
+      function In_Result_Range return Boolean is
+      begin
+         if Is_Static_Subtype (Etype (N)) then
+            return Lo >= Expr_Value (Type_Low_Bound  (Rtyp))
+                     and then
+                   Hi <= Expr_Value (Type_High_Bound (Rtyp));
+         else
+            return Lo >= Expr_Value (Type_Low_Bound  (Base_Type (Rtyp)))
+                     and then
+                   Hi <= Expr_Value (Type_High_Bound (Base_Type (Rtyp)));
+         end if;
+      end In_Result_Range;
+
       ---------
       -- Max --
       ---------
@@ -6738,7 +6779,7 @@ package body Checks is
    --  Start of processing for Minimize_Eliminate_Overflow_Checks
 
    begin
-      --  Case where we do not have an arithmetic operator
+      --  Case where we do not have a signed integer arithmetic operation
 
       if not Is_Signed_Integer_Arithmetic_Op (N) then
 
@@ -6762,18 +6803,168 @@ package body Checks is
 
          return;
 
-      --  If we have an arithmetic oeprator we make recursive calls on the
+      --  Processing for if expression
+
+      elsif Nkind (N) = N_Conditional_Expression then
+         declare
+            Then_DE : constant Node_Id := Next (First (Expressions (N)));
+            Else_DE : constant Node_Id := Next (Then_DE);
+
+         begin
+            Bignum_Operands := False;
+
+            Minimize_Eliminate_Overflow_Checks
+              (Then_DE, Lo, Hi, Top_Level => False);
+
+            if Lo = No_Uint then
+               Bignum_Operands := True;
+            end if;
+
+            Minimize_Eliminate_Overflow_Checks
+              (Else_DE, Rlo, Rhi, Top_Level => False);
+
+            if Rlo = No_Uint then
+               Bignum_Operands := True;
+            else
+               Long_Long_Integer_Operands :=
+                 Etype (Then_DE) = LLIB or else Etype (Else_DE) = LLIB;
+
+               Min (Lo, Rlo);
+               Max (Hi, Rhi);
+            end if;
+
+            --  If at least one of our operands is now bignum, we must rebuild
+            --  the if expression to use bignum operands. We will analyze the
+            --  rebuilt if expression with overflow checks off, since once we
+            --  are in bignum mode, we are all done with overflow checks!
+
+            if Bignum_Operands then
+               Rewrite (N,
+                 Make_Conditional_Expression (Loc,
+                   Expressions => New_List (
+                     Remove_Head (Expressions (N)),
+                     Convert_To_Bignum (Then_DE),
+                     Convert_To_Bignum (Else_DE)),
+                   Is_Elsif    => Is_Elsif (N)));
+
+               Analyze_And_Resolve
+                 (N, RTE (RE_Bignum), Suppress => Overflow_Check);
+
+            --  If we have no Long_Long_Integer operands, then we are in result
+            --  range, since it means that none of our operands felt the need
+            --  to worry about overflow (otherwise it would have already been
+            --  converted to long long integer or bignum).
+
+            elsif not Long_Long_Integer_Operands then
+               Set_Do_Overflow_Check (N, False);
+
+            --  Otherwise convert us to long long integer mode. Note that we
+            --  don't need any further overflow checking at this level.
+
+            else
+               Convert_To_And_Rewrite (LLIB, Then_DE);
+               Convert_To_And_Rewrite (LLIB, Else_DE);
+               Set_Etype (N, LLIB);
+               Set_Do_Overflow_Check (N, False);
+            end if;
+         end;
+
+         return;
+
+      --  Here for case expression
+
+      elsif Nkind (N) = N_Case_Expression then
+         Bignum_Operands := False;
+         Long_Long_Integer_Operands := False;
+         Lo := No_Uint;
+         Hi := No_Uint;
+
+         declare
+            Alt      : Node_Id;
+            New_Alts : List_Id;
+            New_Exp  : Node_Id;
+            Rtype    : Entity_Id;
+
+         begin
+            --  Loop through expressions applying recursive call
+
+            Alt := First (Alternatives (N));
+            while Present (Alt) loop
+               declare
+                  Aexp : constant Node_Id := Expression (Alt);
+
+               begin
+                  Minimize_Eliminate_Overflow_Checks
+                    (Aexp, Lo, Hi, Top_Level => False);
+
+                  if Lo = No_Uint then
+                     Bignum_Operands := True;
+                  elsif Etype (Aexp) = LLIB then
+                     Long_Long_Integer_Operands := True;
+                  end if;
+               end;
+
+               Next (Alt);
+            end loop;
+
+            --  If we have no bignum or long long integer operands, it means
+            --  that none of our dependent expressions could raise overflow.
+            --  In this case, we simply return with no changes except for
+            --  resetting the overflow flag, since we are done with overflow
+            --  checks for this node. We will reset the Analyzed flag so that
+            --  we will properly reexpand and get the needed expansion for
+            --  the case expression.
+
+            if not (Bignum_Operands or else Long_Long_Integer_Operands) then
+               Set_Do_Overflow_Check (N, False);
+               Set_Analyzed (N, False);
+
+            --  Otherwise we are going to rebuild the case expression using
+            --  either bignum or long long integer operands throughout.
+
+            else
+               New_Alts := New_List;
+               Alt := First (Alternatives (N));
+               while Present (Alt) loop
+                  if Bignum_Operands then
+                     New_Exp := Convert_To_Bignum (Expression (Alt));
+                     Rtype   := RTE (RE_Bignum);
+                  else
+                     New_Exp := Convert_To (LLIB, Expression (Alt));
+                     Rtype   := LLIB;
+                  end if;
+
+                  Append_To (New_Alts,
+                    Make_Case_Expression_Alternative (Sloc (Alt),
+                      Actions          => No_List,
+                      Discrete_Choices => Discrete_Choices (Alt),
+                      Expression       => New_Exp));
+
+                  Next (Alt);
+               end loop;
+
+               Rewrite (N,
+                 Make_Case_Expression (Loc,
+                   Expression   => Expression (N),
+                   Alternatives => New_Alts));
+
+               Analyze_And_Resolve (N, Rtype, Suppress => Overflow_Check);
+            end if;
+         end;
+
+         return;
+      end if;
+
+      --  If we have an arithmetic operator we make recursive calls on the
       --  operands to get the ranges (and to properly process the subtree
       --  that lies below us!)
 
-      else
-         Minimize_Eliminate_Overflow_Checks
-           (Right_Opnd (N), Rlo, Rhi, Top_Level => False);
+      Minimize_Eliminate_Overflow_Checks
+        (Right_Opnd (N), Rlo, Rhi, Top_Level => False);
 
-         if Binary then
-            Minimize_Eliminate_Overflow_Checks
-              (Left_Opnd (N), Llo, Lhi, Top_Level => False);
-         end if;
+      if Binary then
+         Minimize_Eliminate_Overflow_Checks
+           (Left_Opnd (N), Llo, Lhi, Top_Level => False);
       end if;
 
       --  If either operand is a bignum, then result will be a bignum
@@ -6788,6 +6979,10 @@ package body Checks is
       else
          Bignum_Operands := False;
 
+         Long_Long_Integer_Operands :=
+           Etype (Right_Opnd (N)) = LLIB
+             or else (Binary and then Etype (Left_Opnd (N)) = LLIB);
+
          case Nkind (N) is
 
             --  Absolute value
@@ -7136,9 +7331,6 @@ package body Checks is
       --  0 .. 1, but the cases are rare and it is not worth the effort.
       --  Failing to do this switching back is only an efficiency issue.
 
-      LLLo := Intval (Type_Low_Bound  (LLIB));
-      LLHi := Intval (Type_High_Bound (LLIB));
-
       if Lo = No_Uint or else Lo < LLLo or else Hi > LLHi then
 
          --  OK, we are definitely outside the range of Long_Long_Integer. The
@@ -7248,6 +7440,14 @@ package body Checks is
          Set_Do_Overflow_Check (N, False);
       end if;
 
+      --  If Result is in range of the result type, and we don't have any
+      --  Long_Long_Integer operands, then overflow checking is not needed
+      --  and we have nothing to do (we have already reset Do_Overflow_Check).
+
+      if In_Result_Range and not Long_Long_Integer_Operands then
+         return;
+      end if;
+
       --  Here we will do the operation in Long_Long_Integer. We do this even
       --  if we know an overflow check is required, better to do this in long
       --  long integer mode, since we are less likely to overflow!
index a43fff7b7c724a1dc08cbd4639e10335ce51c668..29a65f6e32136285c3f29548d445a222a53e8038 100644 (file)
@@ -135,13 +135,14 @@ package Checks is
    --  larger than the overlaid object.
 
    procedure Apply_Arithmetic_Overflow_Check (N : Node_Id);
-   --  Given a binary arithmetic operator (+ - *) expand a software integer
-   --  overflow check using range checks on a larger checking type or a call
-   --  to an appropriate runtime routine. This is used for all three operators
-   --  for the signed integer case, and for +/- in the fixed-point case. The
-   --  check is expanded only if Software_Overflow_Checking is enabled and
-   --  Do_Overflow_Check is set on node N. Note that divide is handled
-   --  separately using Apply_Arithmetic_Divide_Overflow_Check.
+   --  Handle overflow checking for an arithmetic operator. Also handles the
+   --  cases of ELIMINATED and MINIMIZED overflow checking mode. If the mode
+   --  is one of the latter two, then this routine can also be called with
+   --  a conditional expression node to make sure that we properly handle
+   --  overflow checking for dependent expressions. This routine handles
+   --  front end vs back end overflow checks (in the front end case it expands
+   --  the necessary check). Note that divide is handled separately using
+   --  Apply_Arithmetic_Divide_Overflow_Check.
 
    procedure Apply_Constraint_Check
      (N          : Node_Id;
index 1bb9d637f637946c5887b8ace8a6f766cac8fdd9..560d1759ef8bddf6367e536afa53a1db7b271ea6 100644 (file)
@@ -4776,6 +4776,18 @@ package body Exp_Ch4 is
       Fexp    : Node_Id;
 
    begin
+      --  If Do_Overflow_Check is set, it means we are in MINIMIZED/ELIMINATED
+      --  mode, and all we do is to call Apply_Arithmetic_Overflow_Check to
+      --  ensure proper overflow handling for the dependent expressions. The
+      --  checks circuitry will rewrite the case expression in this case with
+      --  Do_Overflow_Checks off. so that when that rewritten node arrives back
+      --  here, then we will do the full expansion.
+
+      if Do_Overflow_Check (N) then
+         Apply_Arithmetic_Overflow_Check (N);
+         return;
+      end if;
+
       --  We expand
 
       --    case X is when A => AX, when B => BX ...
@@ -5204,6 +5216,15 @@ package body Exp_Ch4 is
          --  the same approach as a C conditional expression.
 
       else
+         --  If Do_Overflow_Check is set it means we have a signed intger type
+         --  in MINIMIZED or ELIMINATED mode, so we apply an overflow check to
+         --  the if expression (to make sure that overflow checking is properly
+         --  handled for dependent expressions).
+
+         if Do_Overflow_Check (N) then
+            Apply_Arithmetic_Overflow_Check (N);
+         end if;
+
          return;
       end if;
 
index bf8efcf72fdb58c3ed16bc12993dfb9833877438..39cae8a8659a14f2be932d74d1d518816225897f 100644 (file)
@@ -104,8 +104,7 @@ package body System.Bignums is
 
    function Normalize
      (X   : Digit_Vector;
-      Neg : Boolean := False) return Bignum
-   with Pre  => X'First = 1;
+      Neg : Boolean := False) return Bignum;
    --  Given a digit vector and sign, allocate and construct a Bignum value.
    --  Note that X may have leading zeroes which must be removed, and if the
    --  result is zero, the sign is forced positive.
index d2baee4d64554b4d12afc05f4e5a17d6f49aeb3e..86d74529a8a2c55c05fc536f6e2dd2607f626863 100644 (file)
@@ -5941,6 +5941,16 @@ package body Sem_Res is
 
       Set_Etype (N, Typ);
       Eval_Case_Expression (N);
+
+      --  If we still have a case expression, and overflow checks are enabled
+      --  in MINIMIZED or ELIMINATED modes, then set Do_Overflow_Check to
+      --  ensure that we handle overflow for dependent expressions.
+
+      if Nkind (N) = N_Case_Expression
+        and then Overflow_Check_Mode (Typ) in Minimized_Or_Eliminated
+      then
+         Set_Do_Overflow_Check (N);
+      end if;
    end Resolve_Case_Expression;
 
    -------------------------------
@@ -6134,8 +6144,9 @@ package body Sem_Res is
       Resolve (Then_Expr, Typ);
       Then_Typ := Etype (Then_Expr);
 
-      --  When the "then" and "else" expressions are of a scalar type, insert
-      --  a conversion to ensure the generation of a constraint check.
+      --  When the "then" expression is of a scalar type different from the
+      --  result type, then insert a conversion to ensure the generation of
+      --  a constraint check.
 
       if Is_Scalar_Type (Then_Typ)
         and then Then_Typ /= Typ
@@ -6174,6 +6185,16 @@ package body Sem_Res is
 
       Set_Etype (N, Typ);
       Eval_Conditional_Expression (N);
+
+      --  If we still have a conditional expression, and overflow checks are
+      --  enabled in MINIMIZED or ELIMINATED modes, then set Do_Overflow_Check
+      --  to ensure that we handle overflow for dependent expressions.
+
+      if Nkind (N) = N_Conditional_Expression
+        and then Overflow_Check_Mode (Typ) in Minimized_Or_Eliminated
+      then
+         Set_Do_Overflow_Check (N);
+      end if;
    end Resolve_Conditional_Expression;
 
    -----------------------------------------
index e5773e0d4d94a9ce0c3715131ba5dc1cee73d83d..a7ecd179cc241de8ff56250fda15558e248e0eb7 100644 (file)
@@ -927,6 +927,8 @@ package body Sinfo is
       pragma Assert (False
         or else NT (N).Nkind in N_Op
         or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Case_Expression
+        or else NT (N).Nkind = N_Conditional_Expression
         or else NT (N).Nkind = N_Type_Conversion);
       return Flag17 (N);
    end Do_Overflow_Check;
@@ -3998,6 +4000,8 @@ package body Sinfo is
       pragma Assert (False
         or else NT (N).Nkind in N_Op
         or else NT (N).Nkind = N_Attribute_Reference
+        or else NT (N).Nkind = N_Case_Expression
+        or else NT (N).Nkind = N_Conditional_Expression
         or else NT (N).Nkind = N_Type_Conversion);
       Set_Flag17 (N, Val);
    end Set_Do_Overflow_Check;
index fd595a78ae159d161f8f4ff1fcae8c40daad27b4..79f8c436466a85b5e56f5c40df7469f769437aae 100644 (file)
@@ -823,7 +823,10 @@ package Sinfo is
    --    See also the description of Do_Range_Check for this case. The only
    --    attribute references which use this flag are Pred and Succ, where it
    --    means that the result should be checked for going outside the base
-   --    range. Note that this flag is not set for modular types.
+   --    range. Note that this flag is not set for modular types. This flag is
+   --    also set on conditional expression nodes if we are operating in either
+   --    MINIMIZED or ELIMINATED overflow checking mode (to make sure that we
+   --    properly process overflow checking for dependent expressions).
 
    --  Do_Range_Check (Flag9-Sem)
    --    This flag is set on an expression which appears in a context where a
@@ -3859,18 +3862,91 @@ package Sinfo is
       --  Note on overflow handling: When the overflow checking mode is set to
       --  MINIMIZED or ELIMINATED, nodes for signed arithmetic operations may
       --  be modified to use a larger type for the operands and result. In
-      --  these cases, the back end does not need the Entity field anyway, so
-      --  there is no point in setting it. In fact we reuse the Entity field to
-      --  record the possible range of the result. Entity points to an N_Range
-      --  node whose Low_Bound and High_Bound fields point to integer literal
-      --  nodes containing the computed bounds. These range nodes are only set
-      --  for intermediate nodes whose parents are themselves either arithmetic
-      --  operators, or comparison or membership tests. The computed ranges are
-      --  then used in processing the parent operation. In the case where the
-      --  computed range exceeds that of Long_Long_Integer, and we are running
-      --  in ELIMINATED mode, the operator node will be changed to be a call to
-      --  the appropriate routine in System.Bignums, and in this case we forget
-      --  about keeping track of the range.
+      --  the case where the computed range exceeds that of Long_Long_Integer,
+      --  and we are running in ELIMINATED mode, the operator node will be
+      --  changed to be a call to the appropriate routine in System.Bignums.
+
+      ------------------------------------
+      -- 4.5.7  Conditional Expressions --
+      ------------------------------------
+
+      --  CONDITIONAL_EXPRESSION ::= IF_EXPRESSION | CASE_EXPRESSION
+
+      --------------------------
+      -- 4.5.7  If Expression --
+      ----------------------------
+
+      --  IF_EXPRESSION ::=
+      --    if CONDITION then DEPENDENT_EXPRESSION
+      --                {elsif CONDITION then DEPENDENT_EXPRESSION}
+      --                [else DEPENDENT_EXPRESSION]
+
+      --  DEPENDENT_EXPRESSION ::= EXPRESSION
+
+      --  Note: if we have (IF x1 THEN x2 ELSIF x3 THEN x4 ELSE x5) then it
+      --  is represented as (IF x1 THEN x2 ELSE (IF x3 THEN x4 ELSE x5)) and
+      --  the Is_Elsif flag is set on the inner conditional expression.
+
+      --  Note: to be consistent with the grammar, the following node should
+      --  really be named N_If_Expression, but historically it was always
+      --  N_Conditional_Expression, so it would be a bit of an earthquake
+      --  to change, and actually conditional expression seems a bit clearer
+      --  than if expression in typical contexts, so we decide to leave it!
+
+      --  N_Conditional_Expression
+      --  Sloc points to IF or ELSIF keyword
+      --  Expressions (List1)
+      --  Then_Actions (List2-Sem)
+      --  Else_Actions (List3-Sem)
+      --  Is_Elsif (Flag13) (set if comes from ELSIF)
+      --  Do_Overflow_Check (Flag17-Sem)
+      --  plus fields for expression
+
+      --  Expressions here is a three-element list, whose first element is the
+      --  condition, the second element is the dependent expression after THEN
+      --  and the third element is the dependent expression after the ELSE
+      --  (explicitly set to True if missing).
+
+      --  Note: the Then_Actions and Else_Actions fields are always set to
+      --  No_List in the tree passed to Gigi. These fields are used only
+      --  for temporary processing purposes in the expander.
+
+      ----------------------------
+      -- 4.5.7  Case Expression --
+      ----------------------------
+
+      --  CASE_EXPRESSION ::=
+      --    case SELECTING_EXPRESSION is
+      --      CASE_EXPRESSION_ALTERNATIVE
+      --      {CASE_EXPRESSION_ALTERNATIVE}
+
+      --  Note that the Alternatives cannot include pragmas (this contrasts
+      --  with the situation of case statements where pragmas are allowed).
+
+      --  N_Case_Expression
+      --  Sloc points to CASE
+      --  Expression (Node3) (the selecting expression)
+      --  Alternatives (List4) (the case expression alternatives)
+      --  Do_Overflow_Check (Flag17-Sem)
+
+      ----------------------------------------
+      -- 4.5.7  Case Expression Alternative --
+      ----------------------------------------
+
+      --  CASE_EXPRESSION_ALTERNATIVE ::=
+      --    when DISCRETE_CHOICE_LIST =>
+      --      DEPENDENT_EXPRESSION
+
+      --  N_Case_Expression_Alternative
+      --  Sloc points to WHEN
+      --  Actions (List1)
+      --  Discrete_Choices (List4)
+      --  Expression (Node3)
+
+      --  Note: The Actions field temporarily holds any actions associated with
+      --  evaluation of the Expression. During expansion of the case expression
+      --  these actions are wrapped into an N_Expressions_With_Actions node
+      --  replacing the original expression.
 
       ---------------------------------
       -- 4.5.9 Quantified Expression --
@@ -6877,86 +6953,9 @@ package Sinfo is
    --  show this syntax.
 
    --  Note: Case_Expression and Conditional_Expression is in this section for
-   --  now, since they are extensions. We will move them to their appropriate
-   --  places when they are officially approved as extensions (and then we will
-   --  know what the exact grammar and place in the Reference Manual is!)
-
-      ---------------------
-      -- Case Expression --
-      ---------------------
-
-      --  CASE_EXPRESSION ::=
-      --    case EXPRESSION is
-      --      CASE_EXPRESSION_ALTERNATIVE
-      --      {CASE_EXPRESSION_ALTERNATIVE}
-
-      --  Note that the Alternatives cannot include pragmas (this contrasts
-      --  with the situation of case statements where pragmas are allowed).
-
-      --  N_Case_Expression
-      --  Sloc points to CASE
-      --  Expression (Node3)
-      --  Alternatives (List4)
-
-      ---------------------------------
-      -- Case Expression Alternative --
-      ---------------------------------
-
-      --  CASE_STATEMENT_ALTERNATIVE ::=
-      --    when DISCRETE_CHOICE_LIST =>
-      --      EXPRESSION
-
-      --  N_Case_Expression_Alternative
-      --  Sloc points to WHEN
-      --  Actions (List1)
-      --  Discrete_Choices (List4)
-      --  Expression (Node3)
-
-      --  Note: The Actions field temporarily holds any actions associated with
-      --  evaluation of the Expression. During expansion of the case expression
-      --  these actions are wrapped into an N_Expressions_With_Actions node
-      --  replacing the original expression.
-
-      ----------------------------
-      -- Conditional Expression --
-      ----------------------------
-
-      --  This node is used to represent an expression corresponding to the
-      --  C construct (condition ? then-expression : else_expression), where
-      --  Expressions is a three element list, whose first expression is the
-      --  condition, and whose second and third expressions are the then and
-      --  else expressions respectively.
-
-      --  Note: the Then_Actions and Else_Actions fields are always set to
-      --  No_List in the tree passed to Gigi. These fields are used only
-      --  for temporary processing purposes in the expander.
-
-      --  The Ada language does not permit conditional expressions, however
-      --  this is under discussion as a possible extension by the ARG, and we
-      --  have implemented a form of this capability in GNAT under control of
-      --  the -gnatX switch. The syntax is:
-
-      --  CONDITIONAL_EXPRESSION ::=
-      --    if EXPRESSION then EXPRESSION
-      --                  {elsif EXPRESSION then EXPRESSION}
-      --                  [else EXPRESSION]
-
-      --  And we add the additional constructs
-
-      --  PRIMARY ::= ( CONDITIONAL_EXPRESSION )
-      --  PRAGMA_ARGUMENT_ASSOCIATION ::= CONDITIONAL_EXPRESSION
-
-      --  Note: if we have (IF x1 THEN x2 ELSIF x3 THEN x4 ELSE x5) then it
-      --  is represented as (IF x1 THEN x2 ELSE (IF x3 THEN x4 ELSE x5)) and
-      --  the Is_Elsif flag is set on the inner conditional expression.
-
-      --  N_Conditional_Expression
-      --  Sloc points to IF or ELSIF keyword
-      --  Expressions (List1)
-      --  Then_Actions (List2-Sem)
-      --  Else_Actions (List3-Sem)
-      --  Is_Elsif (Flag13) (set if comes from ELSIF)
-      --  plus fields for expression
+   --  historical reasons, since they were initially extensions. Now that they
+   --  are an official part of Ada 2012, we should move them to the appropriate
+   --  section of this package. ???
 
       --------------
       -- Contract --