aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRobert Dewar <dewar@adacore.com>2012-10-02 08:37:54 +0000
committerArnaud Charlet <charlet@gcc.gnu.org>2012-10-02 10:37:54 +0200
commit4b1c4f20d84963a47ed6c12ea564488c0b224655 (patch)
tree9ee7a8d8942978c3fbfd7342cd658d7e849ae9d5 /gcc
parent2492305bcc43dbc13678f1d6113e76b735dba432 (diff)
downloadgcc-4b1c4f20d84963a47ed6c12ea564488c0b224655.zip
gcc-4b1c4f20d84963a47ed6c12ea564488c0b224655.tar.gz
gcc-4b1c4f20d84963a47ed6c12ea564488c0b224655.tar.bz2
checks.adb (Apply_Arithmetic_Overflow_Checked_Suppressed): New name for Apply_Arithmetic_Overflow_Normal
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ada/ChangeLog19
-rw-r--r--gcc/ada/checks.adb264
-rw-r--r--gcc/ada/checks.ads15
-rw-r--r--gcc/ada/exp_ch4.adb21
-rw-r--r--gcc/ada/s-bignum.adb3
-rw-r--r--gcc/ada/sem_res.adb25
-rw-r--r--gcc/ada/sinfo.adb4
-rw-r--r--gcc/ada/sinfo.ads185
8 files changed, 400 insertions, 136 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 63401fb..8dd037f 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -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
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index f7be383..da20292 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -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!
diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads
index a43fff7..29a65f6 100644
--- a/gcc/ada/checks.ads
+++ b/gcc/ada/checks.ads
@@ -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;
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 1bb9d63..560d175 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -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;
diff --git a/gcc/ada/s-bignum.adb b/gcc/ada/s-bignum.adb
index bf8efcf..39cae8a 100644
--- a/gcc/ada/s-bignum.adb
+++ b/gcc/ada/s-bignum.adb
@@ -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.
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index d2baee4..86d7452 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -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;
-----------------------------------------
diff --git a/gcc/ada/sinfo.adb b/gcc/ada/sinfo.adb
index e5773e0..a7ecd17 100644
--- a/gcc/ada/sinfo.adb
+++ b/gcc/ada/sinfo.adb
@@ -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;
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index fd595a7..79f8c43 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -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 --