From 4b1c4f20d84963a47ed6c12ea564488c0b224655 Mon Sep 17 00:00:00 2001 From: Robert Dewar Date: Tue, 2 Oct 2012 08:37:54 +0000 Subject: checks.adb (Apply_Arithmetic_Overflow_Checked_Suppressed): New name for Apply_Arithmetic_Overflow_Normal 2012-10-02 Robert Dewar * 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 | 19 ++++ gcc/ada/checks.adb | 264 ++++++++++++++++++++++++++++++++++++++++++++------- gcc/ada/checks.ads | 15 +-- gcc/ada/exp_ch4.adb | 21 ++++ gcc/ada/s-bignum.adb | 3 +- gcc/ada/sem_res.adb | 25 ++++- gcc/ada/sinfo.adb | 4 + gcc/ada/sinfo.ads | 185 ++++++++++++++++++------------------ 8 files changed, 400 insertions(+), 136 deletions(-) (limited to 'gcc') 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 + + * 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 * 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 -- -- cgit v1.1