[multiple changes]

2012-10-02  Ben Brosgol  <brosgol@adacore.com>

	* gnat_rm.texi: Minor editing.

2012-10-02  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch6.adb (Analyze_Function_Return): Reject a return
	expression whose type is a local access to subprogram type.

2012-10-02  Robert Dewar  <dewar@adacore.com>

	* sem_eval.adb: Minor improvement to Compile_Time_Compare.

2012-10-02  Robert Dewar  <dewar@adacore.com>

	* checks.adb (Apply_Arithmetic_Overflow_Minimized_Eliminated):
	Fix base type problem that resulted in improper conversion.
	(Minimize_Eliminate_Overflow_Checks): Properly handle top
	level case to avoid unnecessary conversion to bignum or LLI.
	(Minimize_Eliminate_Overflow_Checks): Implement uniform two phase
	approach for arithmetic operators and for if/case expressions.
	* checks.ads: Minor comment fix.
	* exp_ch4.adb (Minimized_Eliminated_Overflow_Check): New function,
	implements a uniform way of treating minimized/eliminated checks in
	two phases.
	(Expand_Compare_Minimize_Eliminate_Overflow): Fix cut and
	paste error resulting in wrong results for less than in some
	cases.	(Expand_Membership_Minimize_Eliminate_Overflow):
	Fix error caused by incorrect capture of operand types.
	(Expand_Membership_Minimize_Eliminate_Overflow): Fix error in
	handling of bignum case.
	(Expand_N_Case_Expression): Implement
	proper two phase handling (Expand_N_If_Expression): Implement
	proper two phase handling (Expand_N_Op_Abs): Implement proper
	two phase handling ditto for all other arithmetic operators
	* sem_res.adb (Resolve_If_Expression): Avoid introducing
	unneeded conversions.

From-SVN: r191980
This commit is contained in:
Arnaud Charlet 2012-10-02 15:05:08 +02:00
parent 6e6636ec8b
commit b6b5cca81b
8 changed files with 465 additions and 131 deletions

View File

@ -1,3 +1,41 @@
2012-10-02 Ben Brosgol <brosgol@adacore.com>
* gnat_rm.texi: Minor editing.
2012-10-02 Ed Schonberg <schonberg@adacore.com>
* sem_ch6.adb (Analyze_Function_Return): Reject a return
expression whose type is a local access to subprogram type.
2012-10-02 Robert Dewar <dewar@adacore.com>
* sem_eval.adb: Minor improvement to Compile_Time_Compare.
2012-10-02 Robert Dewar <dewar@adacore.com>
* checks.adb (Apply_Arithmetic_Overflow_Minimized_Eliminated):
Fix base type problem that resulted in improper conversion.
(Minimize_Eliminate_Overflow_Checks): Properly handle top
level case to avoid unnecessary conversion to bignum or LLI.
(Minimize_Eliminate_Overflow_Checks): Implement uniform two phase
approach for arithmetic operators and for if/case expressions.
* checks.ads: Minor comment fix.
* exp_ch4.adb (Minimized_Eliminated_Overflow_Check): New function,
implements a uniform way of treating minimized/eliminated checks in
two phases.
(Expand_Compare_Minimize_Eliminate_Overflow): Fix cut and
paste error resulting in wrong results for less than in some
cases. (Expand_Membership_Minimize_Eliminate_Overflow):
Fix error caused by incorrect capture of operand types.
(Expand_Membership_Minimize_Eliminate_Overflow): Fix error in
handling of bignum case.
(Expand_N_Case_Expression): Implement
proper two phase handling (Expand_N_If_Expression): Implement
proper two phase handling (Expand_N_Op_Abs): Implement proper
two phase handling ditto for all other arithmetic operators
* sem_res.adb (Resolve_If_Expression): Avoid introducing
unneeded conversions.
2012-10-02 Robert Dewar <dewar@adacore.com>
* s-bignum.adb (Big_Exp): 0**0 should be 1, not 0.

View File

@ -854,7 +854,7 @@ package body Checks is
if Is_Signed_Integer_Type (Typ)
and then Nkind (Parent (N)) = N_Type_Conversion
then
declare
Conversion_Optimization : declare
Target_Type : constant Entity_Id :=
Base_Type (Entity (Subtype_Mark (Parent (N))));
@ -918,7 +918,7 @@ package body Checks is
end if;
end if;
end if;
end;
end Conversion_Optimization;
end if;
-- Now see if an overflow check is required
@ -1129,9 +1129,11 @@ package body Checks is
-- top level, we have the proper type. This "undoing" is a point at
-- which a final overflow check may be applied.
-- If the result type was not fiddled we are all set
-- If the result type was not fiddled we are all set. We go to base
-- types here because things may have been rewritten to generate the
-- base type of the operand types.
if Etype (Op) = Result_Type then
if Base_Type (Etype (Op)) = Base_Type (Result_Type) then
return;
-- Bignum case
@ -1204,10 +1206,13 @@ package body Checks is
Analyze_And_Resolve (Op);
end;
-- Here we know the result is Long_Long_Integer'Base
-- Here we know the result is Long_Long_Integer'Base, or that it
-- has been rewritten because the parent is a conversion (see
-- Apply_Arithmetic_Overflow_Check.Conversion_Optimization).
else
pragma Assert (Etype (Op) = LLIB);
pragma Assert
(Etype (Op) = LLIB or else Nkind (Parent (Op)) = N_Type_Conversion);
-- All we need to do here is to convert the result to the proper
-- result type. As explained above for the Bignum case, we can
@ -6682,6 +6687,35 @@ package body Checks is
-- Minimize_Eliminate_Overflow_Checks --
----------------------------------------
-- This is a recursive routine that is called at the top of an expression
-- tree to properly process overflow checking for a whole subtree by making
-- recursive calls to process operands. This processing may involve the use
-- of bignum or long long integer arithmetic, which will change the types
-- of operands and results. That's why we can't do this bottom up (since
-- it would intefere with semantic analysis).
-- What happens is that if Minimized/Eliminated mode is in effect then
-- the operator expansion routines, as well as the expansion routines
-- for if/case expression test the Do_Overflow_Check flag and if it is
-- set they (for the moment) do nothing except call the routine to apply
-- the overflow check (Apply_Arithmetic_Overflow_Check). That routine
-- does nothing for non top-level nodes, so at the point where the call
-- is made for the top level node, the entire expression subtree has not
-- been expanded, or processed for overflow. All that has to happen as a
-- result of the top level call to this routine.
-- As noted above, the overflow processing works by making recursive calls
-- for the operands, and figuring out what to do, based on the processing
-- of these operands (e.g. if a bignum operand appears, the parent op has
-- to be done in bignum mode), and the determined ranges of the operands.
-- After possible rewriting of a constituent subexpression node, a call is
-- made to reanalyze the node after setting Analyzed to False. To avoid a
-- recursive call into the whole overflow apparatus, and important rule for
-- this reanalysis call is that either Do_Overflow_Check must be False, or
-- if it is set, then the overflow checking mode must be temporarily set
-- to Checked/Suppressed. Either step will avoid the unwanted recursion.
procedure Minimize_Eliminate_Overflow_Checks
(N : Node_Id;
Lo : out Uint;
@ -6743,10 +6777,14 @@ package body Checks is
function In_Result_Range return Boolean is
begin
if Is_Static_Subtype (Etype (N)) then
if Lo = No_Uint or else Hi = No_Uint then
return False;
elsif 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
@ -6853,10 +6891,13 @@ package body Checks is
-- 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).
-- converted to long long integer or bignum). We reanalyze to
-- complete the expansion of the if expression
elsif not Long_Long_Integer_Operands then
Set_Do_Overflow_Check (N, False);
Set_Analyzed (N, False);
Analyze_And_Resolve (N, Suppress => Overflow_Check);
-- Otherwise convert us to long long integer mode. Note that we
-- don't need any further overflow checking at this level.
@ -6865,7 +6906,12 @@ package body Checks is
Convert_To_And_Rewrite (LLIB, Then_DE);
Convert_To_And_Rewrite (LLIB, Else_DE);
Set_Etype (N, LLIB);
-- Now reanalyze with overflow checks off
Set_Do_Overflow_Check (N, False);
Set_Analyzed (N, False);
Analyze_And_Resolve (N, LLIB, Suppress => Overflow_Check);
end if;
end;
@ -6880,10 +6926,7 @@ package body Checks is
Hi := No_Uint;
declare
Alt : Node_Id;
New_Alts : List_Id;
New_Exp : Node_Id;
Rtype : Entity_Id;
Alt : Node_Id;
begin
-- Loop through expressions applying recursive call
@ -6915,40 +6958,48 @@ package body Checks is
-- we will properly reexpand and get the needed expansion for
-- the case expression.
if not (Bignum_Operands or else Long_Long_Integer_Operands) then
if not (Bignum_Operands or Long_Long_Integer_Operands) then
Set_Do_Overflow_Check (N, False);
Set_Analyzed (N, False);
Analyze_And_Resolve (N, Suppress => Overflow_Check);
-- 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;
declare
Rtype : Entity_Id;
New_Alts : List_Id;
New_Exp : Node_Id;
Append_To (New_Alts,
Make_Case_Expression_Alternative (Sloc (Alt),
Actions => No_List,
Discrete_Choices => Discrete_Choices (Alt),
Expression => New_Exp));
begin
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;
Next (Alt);
end loop;
Append_To (New_Alts,
Make_Case_Expression_Alternative (Sloc (Alt),
Actions => No_List,
Discrete_Choices => Discrete_Choices (Alt),
Expression => New_Exp));
Rewrite (N,
Make_Case_Expression (Loc,
Expression => Expression (N),
Alternatives => New_Alts));
Next (Alt);
end loop;
Analyze_And_Resolve (N, Rtype, Suppress => Overflow_Check);
Rewrite (N,
Make_Case_Expression (Loc,
Expression => Expression (N),
Alternatives => New_Alts));
Analyze_And_Resolve (N, Rtype, Suppress => Overflow_Check);
end;
end if;
end;
@ -6967,7 +7018,17 @@ package body Checks is
(Left_Opnd (N), Llo, Lhi, Top_Level => False);
end if;
-- If either operand is a bignum, then result will be a bignum
-- Record if we have Long_Long_Integer operands
Long_Long_Integer_Operands :=
Etype (Right_Opnd (N)) = LLIB
or else (Binary and then Etype (Left_Opnd (N)) = LLIB);
-- If either operand is a bignum, then result will be a bignum and we
-- don't need to do any range analysis. As previously discussed we could
-- do range analysis in such cases, but it could mean working with giant
-- numbers at compile time for very little gain (the number of cases
-- in which we could slip back from bignum mode are small).
if Rlo = No_Uint or else (Binary and then Llo = No_Uint) then
Lo := No_Uint;
@ -7321,7 +7382,59 @@ package body Checks is
end case;
end if;
-- Case where we do the operation in Bignum mode. This happens either
-- If we know we are in the result range, and we do not have Bignum
-- operands or Long_Long_Integer operands, we can just renalyze with
-- overflow checks turned off (since we know we cannot have overflow).
-- As always the reanalysis is required to complete expansion of the
-- operator, and we prevent recursion by suppressing the check.
if not (Bignum_Operands or Long_Long_Integer_Operands)
and then In_Result_Range
then
Set_Do_Overflow_Check (N, False);
Set_Analyzed (N, False);
Analyze_And_Resolve (N, Suppress => Overflow_Check);
return;
-- Here we know that we are not in the result range, and in the general
-- we will move into either the Bignum or Long_Long_Integer domain to
-- compute the result. However, there is one exception. If we are at the
-- top level, and we do not have Bignum or Long_Long_Integer operands,
-- we will have to immediately convert the result back to the result
-- type, so there is no point in Bignum/Long_Long_Integer fiddling.
elsif Top_Level
and then not (Bignum_Operands or Long_Long_Integer_Operands)
then
-- Here we will keep the original types, but we do need an overflow
-- check, so we will set Do_Overflow_Check to True (actually it is
-- true already, or how would we have got here?).
pragma Assert (Do_Overflow_Check (N));
Set_Analyzed (N, False);
-- One subtlety. We can't just go ahead and do an analyze operation
-- here because it will cause recursion into the whole minimized/
-- eliminated overflow processing which is not what we want. Here
-- we are at the top level, and we need a check against the result
-- mode (i.e. we want to use Checked mode). So do exactly that!
declare
Svg : constant Overflow_Check_Type :=
Scope_Suppress.Overflow_Checks_General;
Sva : constant Overflow_Check_Type :=
Scope_Suppress.Overflow_Checks_Assertions;
begin
Scope_Suppress.Overflow_Checks_General := Checked;
Scope_Suppress.Overflow_Checks_Assertions := Checked;
Analyze_And_Resolve (N);
Scope_Suppress.Overflow_Checks_General := Svg;
Scope_Suppress.Overflow_Checks_Assertions := Sva;
end;
return;
-- Cases where we do the operation in Bignum mode. This happens either
-- because one of our operands is in Bignum mode already, or because
-- the computed bounds are outside the bounds of Long_Long_Integer,
-- which in some cases can be indicated by Hi and Lo being No_Uint.
@ -7331,10 +7444,10 @@ 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.
if Lo = No_Uint or else Lo < LLLo or else Hi > LLHi then
elsif Lo = No_Uint or else Lo < LLLo or else Hi > LLHi then
-- OK, we are definitely outside the range of Long_Long_Integer. The
-- question is whether to move into Bignum mode, or remain the domain
-- question is whether to move to Bignum mode, or stay in the domain
-- of Long_Long_Integer, signalling that an overflow check is needed.
-- Obviously in MINIMIZED mode we stay with LLI, since we are not in
@ -7440,12 +7553,21 @@ 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).
-- Here we are not in Bignum territory, but we may have long long
-- integer operands that need special handling. First a special check:
-- If an exponentiation operator exponent is of type Long_Long_Integer,
-- it means we converted it to prevent overflow, but exponentiation
-- requires a Natural right operand, so convert it back to Natural.
-- This conversion may raise an exception which is fine.
if In_Result_Range and not Long_Long_Integer_Operands then
return;
if Nkind (N) = N_Op_Expon and then Etype (Right_Opnd (N)) = LLIB then
Convert_To_And_Rewrite (Standard_Natural, Right_Opnd (N));
-- Now Long_Long_Integer_Operands may have to be reset if that was
-- the only long long integer operand, i.e. we now have long long
-- integer operands only if the left operand is long long integer.
Long_Long_Integer_Operands := Etype (Left_Opnd (N)) = LLIB;
end if;
-- Here we will do the operation in Long_Long_Integer. We do this even

View File

@ -142,7 +142,7 @@ package Checks is
-- 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.
-- Apply_Divide_Checks.
procedure Apply_Constraint_Check
(N : Node_Id;

View File

@ -212,6 +212,21 @@ package body Exp_Ch4 is
-- constrained type (the caller has ensured this by using
-- Convert_To_Actual_Subtype if necessary).
function Minimized_Eliminated_Overflow_Check (N : Node_Id) return Boolean;
-- For signed arithmetic operations with Do_Overflow_Check set when the
-- current overflow mode is MINIMIZED or ELIMINATED, we need to make a
-- call to Apply_Arithmetic_Overflow_Checks as the first thing we do. We
-- then return. We count on the recursive apparatus for overflow checks
-- to call us back with an equivalent operation that does not have the
-- Do_Overflow_Check flag set, and that is when we will proceed with the
-- expansion of the operator (e.g. converting X+0 to X, or X**2 to X*X).
-- We cannot do these optimizations without first making this check, since
-- there may be operands further down the tree that are relying on the
-- recursive calls triggered by the top level nodes to properly process
-- overflow checking and remaining expansion on these nodes. Note that
-- this call back may be skipped if the operation is done in Bignum mode
-- but that's fine, since the Bignum call takes care of everything.
procedure Optimize_Length_Comparison (N : Node_Id);
-- Given an expression, if it is of the form X'Length op N (or the other
-- way round), where N is known at compile time to be 0 or 1, and X is a
@ -2383,9 +2398,9 @@ package body Exp_Ch4 is
when N_Op_Lt =>
if Llo >= Rhi then
Set_True;
elsif Lhi < Rlo then
Set_False;
elsif Lhi < Rlo then
Set_True;
end if;
when N_Op_Ne =>
@ -3721,11 +3736,14 @@ package body Exp_Ch4 is
-- Despite the name, this routine applies only to N_In, not to
-- N_Not_In. The latter is always rewritten as not (X in Y).
Loc : constant Source_Ptr := Sloc (N);
Lop : constant Node_Id := Left_Opnd (N);
Rop : constant Node_Id := Right_Opnd (N);
Ltype : constant Entity_Id := Etype (Lop);
Rtype : constant Entity_Id := Etype (Rop);
Loc : constant Source_Ptr := Sloc (N);
Lop : constant Node_Id := Left_Opnd (N);
Rop : constant Node_Id := Right_Opnd (N);
-- Note: there are many referencs to Etype (Lop) and Etype (Rop). It
-- is thus tempting to capture these values, but due to the rewrites
-- that occur as a result of overflow checking, these values change
-- as we go along, and it is safe just to always use Etype explicitly.
Restype : constant Entity_Id := Etype (N);
-- Save result type
@ -3743,19 +3761,24 @@ package body Exp_Ch4 is
-- predicate, then we can just replace the right operand with an
-- explicit range T'First .. T'Last, and use the explicit range code.
if Nkind (Rop) /= N_Range and then No (Predicate_Function (Rtype)) then
Rewrite (Rop,
Make_Range (Loc,
Low_Bound =>
Make_Attribute_Reference (Loc,
Attribute_Name => Name_First,
Prefix => New_Reference_To (Rtype, Loc)),
High_Bound =>
Make_Attribute_Reference (Loc,
Attribute_Name => Name_Last,
Prefix => New_Reference_To (Rtype, Loc))));
Analyze_And_Resolve (Rop, Rtype, Suppress => All_Checks);
if Nkind (Rop) /= N_Range
and then No (Predicate_Function (Etype (Rop)))
then
declare
Rtyp : constant Entity_Id := Etype (Rop);
begin
Rewrite (Rop,
Make_Range (Loc,
Low_Bound =>
Make_Attribute_Reference (Loc,
Attribute_Name => Name_First,
Prefix => New_Reference_To (Rtyp, Loc)),
High_Bound =>
Make_Attribute_Reference (Loc,
Attribute_Name => Name_Last,
Prefix => New_Reference_To (Rtyp, Loc))));
Analyze_And_Resolve (Rop, Rtyp, Suppress => All_Checks);
end;
end if;
-- Here for the explicit range case. Note that the bounds of the range
@ -3763,7 +3786,7 @@ package body Exp_Ch4 is
if Nkind (Rop) = N_Range then
Minimize_Eliminate_Overflow_Checks
(Low_Bound (Rop), Lo, Hi, Top_Level => False);
(Low_Bound (Rop), Lo, Hi, Top_Level => False);
Minimize_Eliminate_Overflow_Checks
(High_Bound (Rop), Lo, Hi, Top_Level => False);
@ -3771,7 +3794,7 @@ package body Exp_Ch4 is
-- Bignum case
if Is_RTE (Ltype, RE_Bignum)
if Is_RTE (Etype (Lop), RE_Bignum)
or else Is_RTE (Etype (Low_Bound (Rop)), RE_Bignum)
or else Is_RTE (Etype (High_Bound (Rop)), RE_Bignum)
then
@ -3841,9 +3864,9 @@ package body Exp_Ch4 is
else
-- Case where types are all the same
if Ltype = Etype (Low_Bound (Rop))
if Base_Type (Etype (Lop)) = Base_Type (Etype (Low_Bound (Rop)))
and then
Ltype = Etype (High_Bound (Rop))
Base_Type (Etype (Lop)) = Base_Type (Etype (High_Bound (Rop)))
then
null;
@ -3862,7 +3885,8 @@ package body Exp_Ch4 is
end if;
-- Now the three operands are of the same signed integer type,
-- so we can use the normal expansion routine for membership.
-- so we can use the normal expansion routine for membership,
-- setting the flag to prevent recursion into this procedure.
Set_No_Minimize_Eliminate (N);
Expand_N_In (N);
@ -3873,17 +3897,17 @@ package body Exp_Ch4 is
-- the standard N_In circuitry with appropriate types.
else
pragma Assert (Present (Predicate_Function (Rtype)));
pragma Assert (Present (Predicate_Function (Etype (Rop))));
-- If types are "right", just call Expand_N_In preventing recursion
if Base_Type (Ltype) = Base_Type (Rtype) then
if Base_Type (Etype (Lop)) = Base_Type (Etype (Rop)) then
Set_No_Minimize_Eliminate (N);
Expand_N_In (N);
-- Bignum case
elsif Is_RTE (Ltype, RE_Bignum) then
elsif Is_RTE (Etype (Lop), RE_Bignum) then
-- For X in T, we want to insert code that looks like
@ -3911,11 +3935,11 @@ package body Exp_Ch4 is
-- A bit gruesome, but here goes.
declare
Blk : constant Node_Id := Make_Bignum_Block (Loc);
Bnn : constant Entity_Id := Make_Temporary (Loc, 'B', N);
Lnn : constant Entity_Id := Make_Temporary (Loc, 'L', N);
Nnn : constant Entity_Id := Make_Temporary (Loc, 'N', N);
Nin : Node_Id;
Blk : constant Node_Id := Make_Bignum_Block (Loc);
Bnn : constant Entity_Id := Make_Temporary (Loc, 'B', N);
Lnn : constant Entity_Id := Make_Temporary (Loc, 'L', N);
Nnn : constant Entity_Id := Make_Temporary (Loc, 'N', N);
Nin : Node_Id;
begin
-- The last membership test is marked to prevent recursion
@ -3923,9 +3947,9 @@ package body Exp_Ch4 is
Nin :=
Make_In (Loc,
Left_Opnd =>
Convert_To (Base_Type (Rtype),
Convert_To (Base_Type (Etype (Rop)),
New_Occurrence_Of (Lnn, Loc)),
Right_Opnd => New_Occurrence_Of (Rtype, Loc));
Right_Opnd => New_Occurrence_Of (Etype (Rop), Loc));
Set_No_Minimize_Eliminate (Nin);
-- Now decorate the block
@ -3985,7 +4009,7 @@ package body Exp_Ch4 is
New_Occurrence_Of (Lnn, Loc),
Right_Opnd =>
New_Occurrence_Of
(Base_Type (Rtype), Loc)),
(Base_Type (Etype (Rop)), Loc)),
Right_Opnd => Nin))))));
Insert_Actions (N, New_List (
@ -4001,10 +4025,10 @@ package body Exp_Ch4 is
end;
-- Not bignum case, but types don't match (this means we rewrote the
-- left operand to be Long_Long_Integer.
-- left operand to be Long_Long_Integer).
else
pragma Assert (Base_Type (Ltype) = LLIB);
pragma Assert (Base_Type (Etype (Lop)) = LLIB);
-- We rewrite the membership test as
@ -4019,8 +4043,9 @@ package body Exp_Ch4 is
Nin :=
Make_In (Loc,
Left_Opnd =>
Convert_To (Base_Type (Rtype), Duplicate_Subexpr (Lop)),
Right_Opnd => New_Occurrence_Of (Rtype, Loc));
Convert_To (Base_Type (Etype (Rop)),
Duplicate_Subexpr (Lop)),
Right_Opnd => New_Occurrence_Of (Etype (Rop), Loc));
Set_No_Minimize_Eliminate (Nin);
-- Now do the rewrite
@ -4031,7 +4056,7 @@ package body Exp_Ch4 is
Make_In (Loc,
Left_Opnd => Lop,
Right_Opnd =>
New_Occurrence_Of (Base_Type (Ltype), Loc)),
New_Occurrence_Of (Base_Type (Etype (Lop)), Loc)),
Right_Opnd => Nin));
Analyze_And_Resolve (N, Restype, Suppress => All_Checks);
@ -4776,14 +4801,9 @@ 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.
-- Check for MINIMIZED/ELIMINATED overflow mode
if Do_Overflow_Check (N) then
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
@ -5170,6 +5190,13 @@ package body Exp_Ch4 is
New_N : Node_Id;
begin
-- Check for MINIMIZED/ELIMINATED overflow mode
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
-- Fold at compile time if condition known. We have already folded
-- static if expressions, but it is possible to fold any case in which
-- the condition is known at compile time, even though the result is
@ -5383,15 +5410,6 @@ 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;
@ -5500,18 +5518,35 @@ package body Exp_Ch4 is
-- Check case of explicit test for an expression in range of its
-- subtype. This is suspicious usage and we replace it with a 'Valid
-- test and give a warning. For floating point types however, this is a
-- standard way to check for finite numbers, and using 'Valid would
-- typically be a pessimization. Also skip this test for predicated
-- types, since it is perfectly reasonable to check if a value meets
-- its predicate.
-- test and give a warning for scalar types.
if Is_Scalar_Type (Ltyp)
-- Only relevant for source comparisons
and then Comes_From_Source (N)
-- In floating-point this is a standard way to check for finite values
-- and using 'Valid would typically be a pessimization.
and then not Is_Floating_Point_Type (Ltyp)
-- Don't give the message unless right operand is a type entity and
-- the type of the left operand matches this type. Note that this
-- eliminates the cases where MINIMIZED/ELIMINATED mode overflow
-- checks have changed the type of the left operand.
and then Nkind (Rop) in N_Has_Entity
and then Ltyp = Entity (Rop)
and then Comes_From_Source (N)
-- Skip in VM mode, where we have no sense of invalid values. The
-- warning still seems relevant, but not important enough to worry.
and then VM_Target = No_VM
-- Skip this for predicated types, where such expressions are a
-- reasonable way of testing if something meets the predicate.
and then not (Is_Discrete_Type (Ltyp)
and then Present (Predicate_Function (Ltyp)))
then
@ -5564,15 +5599,30 @@ package body Exp_Ch4 is
-- Could use some individual comments for this complex test ???
if Is_Scalar_Type (Ltyp)
-- And left operand is X'First where X matches left operand
-- type (this eliminates cases of type mismatch, including
-- the cases where ELIMINATED/MINIMIZED mode has changed the
-- type of the left operand.
and then Nkind (Lo_Orig) = N_Attribute_Reference
and then Attribute_Name (Lo_Orig) = Name_First
and then Nkind (Prefix (Lo_Orig)) in N_Has_Entity
and then Entity (Prefix (Lo_Orig)) = Ltyp
-- Same tests for right operand
and then Nkind (Hi_Orig) = N_Attribute_Reference
and then Attribute_Name (Hi_Orig) = Name_Last
and then Nkind (Prefix (Hi_Orig)) in N_Has_Entity
and then Entity (Prefix (Hi_Orig)) = Ltyp
-- Relevant only for source cases
and then Comes_From_Source (N)
-- Omit for VM cases, where we don't have invalid values
and then VM_Target = No_VM
then
Substitute_Valid_Check;
@ -6331,6 +6381,13 @@ package body Exp_Ch4 is
begin
Unary_Op_Validity_Checks (N);
-- Check for MINIMIZED/ELIMINATED overflow mode
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
-- Deal with software overflow checking
if not Backend_Overflow_Checks_On_Target
@ -6374,6 +6431,13 @@ package body Exp_Ch4 is
begin
Binary_Op_Validity_Checks (N);
-- Check for MINIMIZED/ELIMINATED overflow mode
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
-- N + 0 = 0 + N = N for integer types
if Is_Integer_Type (Typ) then
@ -6516,6 +6580,15 @@ package body Exp_Ch4 is
begin
Binary_Op_Validity_Checks (N);
-- Check for MINIMIZED/ELIMINATED overflow mode
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
-- Otherwise proceed with expansion of division
if Rknow then
Rval := Expr_Value (Ropnd);
end if;
@ -7284,19 +7357,9 @@ package body Exp_Ch4 is
end;
end if;
-- Normally we complete expansion of exponentiation (e.g. converting
-- to multplications) right here, but there is one exception to this.
-- If we have a signed integer type and the overflow checking mode
-- is MINIMIZED or ELIMINATED and overflow checking is activated, then
-- we don't yet want to expand, since that will intefere with handling
-- of extended precision intermediate value. In this situation we just
-- apply the arithmetic overflow check, and then the overflow check
-- circuit will re-expand the exponentiation node in CHECKED mode.
-- Check for MINIMIZED/ELIMINATED overflow mode
if Is_Signed_Integer_Type (Rtyp)
and then Overflow_Check_Mode (Typ) in Minimized_Or_Eliminated
and then Do_Overflow_Check (N)
then
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
@ -7792,6 +7855,13 @@ package body Exp_Ch4 is
begin
Unary_Op_Validity_Checks (N);
-- Check for MINIMIZED/ELIMINATED overflow mode
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
if not Backend_Overflow_Checks_On_Target
and then Is_Signed_Integer_Type (Etype (N))
and then Do_Overflow_Check (N)
@ -7819,11 +7889,12 @@ package body Exp_Ch4 is
procedure Expand_N_Op_Mod (N : Node_Id) is
Loc : constant Source_Ptr := Sloc (N);
Typ : constant Entity_Id := Etype (N);
Left : constant Node_Id := Left_Opnd (N);
Right : constant Node_Id := Right_Opnd (N);
DOC : constant Boolean := Do_Overflow_Check (N);
DDC : constant Boolean := Do_Division_Check (N);
Left : Node_Id;
Right : Node_Id;
LLB : Uint;
Llo : Uint;
Lhi : Uint;
@ -7837,10 +7908,29 @@ package body Exp_Ch4 is
begin
Binary_Op_Validity_Checks (N);
-- Check for MINIMIZED/ELIMINATED overflow mode
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
if Is_Integer_Type (Etype (N)) then
Apply_Divide_Checks (N);
-- All done if we don't have a MOD any more, which can happen as a
-- result of overflow expansion in MINIMIZED or ELIMINATED modes.
if Nkind (N) /= N_Op_Mod then
return;
end if;
end if;
-- Proceed with expansion of mod operator
Left := Left_Opnd (N);
Right := Right_Opnd (N);
Determine_Range (Right, ROK, Rlo, Rhi, Assume_Valid => True);
Determine_Range (Left, LOK, Llo, Lhi, Assume_Valid => True);
@ -7960,6 +8050,13 @@ package body Exp_Ch4 is
begin
Binary_Op_Validity_Checks (N);
-- Check for MINIMIZED/ELIMINATED overflow mode
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
-- Special optimizations for integer types
if Is_Integer_Type (Typ) then
@ -8482,6 +8579,13 @@ package body Exp_Ch4 is
procedure Expand_N_Op_Plus (N : Node_Id) is
begin
Unary_Op_Validity_Checks (N);
-- Check for MINIMIZED/ELIMINATED overflow mode
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
end Expand_N_Op_Plus;
---------------------
@ -8492,8 +8596,8 @@ package body Exp_Ch4 is
Loc : constant Source_Ptr := Sloc (N);
Typ : constant Entity_Id := Etype (N);
Left : constant Node_Id := Left_Opnd (N);
Right : constant Node_Id := Right_Opnd (N);
Left : Node_Id;
Right : Node_Id;
Lo : Uint;
Hi : Uint;
@ -8508,10 +8612,29 @@ package body Exp_Ch4 is
begin
Binary_Op_Validity_Checks (N);
-- Check for MINIMIZED/ELIMINATED overflow mode
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
if Is_Integer_Type (Etype (N)) then
Apply_Divide_Checks (N);
-- All done if we don't have a REM any more, which can happen as a
-- result of overflow expansion in MINIMIZED or ELIMINATED modes.
if Nkind (N) /= N_Op_Rem then
return;
end if;
end if;
-- Proceed with expansion of REM
Left := Left_Opnd (N);
Right := Right_Opnd (N);
-- Apply optimization x rem 1 = 0. We don't really need that with gcc,
-- but it is useful with other back ends (e.g. AAMP), and is certainly
-- harmless.
@ -8624,6 +8747,13 @@ package body Exp_Ch4 is
begin
Binary_Op_Validity_Checks (N);
-- Check for MINIMIZED/ELIMINATED overflow mode
if Minimized_Eliminated_Overflow_Check (N) then
Apply_Arithmetic_Overflow_Check (N);
return;
end if;
-- N - 0 = N for integer types
if Is_Integer_Type (Typ)
@ -11626,6 +11756,18 @@ package body Exp_Ch4 is
return Func_Body;
end Make_Boolean_Array_Op;
-----------------------------------------
-- Minimized_Eliminated_Overflow_Check --
-----------------------------------------
function Minimized_Eliminated_Overflow_Check (N : Node_Id) return Boolean is
begin
return
Is_Signed_Integer_Type (Etype (N))
and then Do_Overflow_Check (N)
and then Overflow_Check_Mode (Empty) in Minimized_Or_Eliminated;
end Minimized_Eliminated_Overflow_Check;
--------------------------------
-- Optimize_Length_Comparison --
--------------------------------
@ -12216,7 +12358,7 @@ package body Exp_Ch4 is
end if;
end Is_Safe_Operand;
-- Start of processing for Is_Safe_In_Place_Array_Op
-- Start of processing for Safe_In_Place_Array_Op
begin
-- Skip this processing if the component size is different from system

View File

@ -4147,7 +4147,8 @@ MODE ::= SUPPRESSED | CHECKED | MINIMIZED | ELIMINATED
@noindent
This pragma sets the current overflow mode to the given mode. For details
of the meaning of these modes, see section on overflow checking in the
of the meaning of these modes, please refer to the
``Overflow Check Handling in GNAT'' appendix in the
@value{EDITION} User's Guide. If only the @code{General} parameter is present,
the given mode applies to all expressions. If both parameters are present,
the @code{General} mode applies to expressions outside assertions, and
@ -4169,6 +4170,7 @@ The pragma @code{Suppress (Overflow_Check)} sets mode
General => Suppressed
@end smallexample
@noindent
suppressing all overflow checking within and outside
assertions.
@ -4178,9 +4180,11 @@ The pragam @code{Unsuppress (Overflow_Check)} sets mode
General => Checked
@end smallexample
@noindent
which causes overflow checking of all intermediate overflows.
This applies both inside and outside assertions.
@node Pragma Passive
@unnumberedsec Pragma Passive
@findex Passive

View File

@ -869,6 +869,24 @@ package body Sem_Ch6 is
then
Rewrite (Expr, Convert_To (R_Type, Relocate_Node (Expr)));
Analyze_And_Resolve (Expr, R_Type);
-- If this is a local anonymous access to subprogram, the
-- accessibility check can be applied statically. The return is
-- illegal if the access type of the return expression is declared
-- inside of the subprogram (except if it is the subtype indication
-- of an extended return statement).
elsif Ekind (R_Type) = E_Anonymous_Access_Subprogram_Type then
if not Comes_From_Source (Current_Scope)
or else Ekind (Current_Scope) = E_Return_Statement
then
null;
elsif
Scope_Depth (Scope (Etype (Expr))) >= Scope_Depth (Scope_Id)
then
Error_Msg_N ("cannot return local access to subprogram", N);
end if;
end if;
-- If the result type is class-wide, then check that the return

View File

@ -949,21 +949,31 @@ package body Sem_Eval is
LLo, LHi : Uint;
RLo, RHi : Uint;
Single : Boolean;
-- True if each range is a single point
begin
Determine_Range (L, LOK, LLo, LHi, Assume_Valid);
Determine_Range (R, ROK, RLo, RHi, Assume_Valid);
if LOK and ROK then
Single := (LLo = LHi) and then (RLo = RHi);
if LHi < RLo then
if Single and Assume_Valid then
Diff.all := RLo - LLo;
end if;
return LT;
elsif RHi < LLo then
if Single and Assume_Valid then
Diff.all := LLo - RLo;
end if;
return GT;
elsif LLo = LHi
and then RLo = RHi
and then LLo = RLo
then
elsif Single and then LLo = RLo then
-- If the range includes a single literal and we can assume
-- validity then the result is known even if an operand is

View File

@ -7162,7 +7162,7 @@ package body Sem_Res is
-- a constraint check.
if Is_Scalar_Type (Then_Typ)
and then Then_Typ /= Typ
and then Base_Type (Then_Typ) /= Base_Type (Typ)
then
Rewrite (Then_Expr, Convert_To (Typ, Then_Expr));
Analyze_And_Resolve (Then_Expr, Typ);