summaryrefslogtreecommitdiff
path: root/gcc/ada/sem_eval.adb
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-19 18:19:39 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-19 18:19:39 +0000
commite56043cd2c207982e812ce6fcecb7353dea58363 (patch)
tree01a6f37ad5a9ae6b18bdc20f052b04e19b4255c0 /gcc/ada/sem_eval.adb
parent2e02a1a4548f2ee1ea519c88e68b20621ad16fcc (diff)
downloadgcc-e56043cd2c207982e812ce6fcecb7353dea58363.tar.gz
2010-09-19 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 164348, with some improvements in gcc/melt-runtime.[ch] 2010-09-19 Basile Starynkevitch <basile@starynkevitch.net> [[merged with trunk rev.164348, so improved MELT runtime!]] * gcc/melt-runtime.h: improved comments. (melt_debug_garbcoll, melt_debuggc_eprintf): Moved from melt-runtime.c. (melt_obmag_string): New declaration. (struct meltobject_st, struct meltclosure_st, struct meltroutine_st, struct meltmixbigint_st, struct meltstring_st): using GTY variable_size and @@MELTGTY@@ comment. (melt_mark_special): added debug print. * gcc/melt-runtime.c: Improved comments. Include bversion.h, realmpfr.h, gimple-pretty-print.h. (ggc_force_collect) Declared external. (melt_forward_counter): Added. (melt_obmag_string): New function. (melt_alptr_1, melt_alptr_2, melt_break_alptr_1_at) (melt_break_alptr_2_at, melt_break_alptr_1,melt_break_alptr_1) (melt_allocate_young_gc_zone, melt_free_young_gc_zone): New. (delete_special, meltgc_make_special): Improved debug printf and use melt_break_alptr_1... (ggc_alloc_*) macros defined for backport to GCC 4.5 (melt_forwarded_copy): Don't clear the new destination zone in old GGC heap. (meltgc_add_out_raw_len): Use ggc_alloc_atomic. (meltgc_raw_new_mappointers, meltgc_raw_put_mappointers) (meltgc_raw_remove_mappointers): Corrected length argument to ggc_alloc_cleared_vec_entrypointermelt_st. (melt_really_initialize): Call melt_allocate_young_gc_zone. (melt_initialize): Set flag_plugin_added. (melt_val2passflag): TODO_verify_loops only in GCC 4.5 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@164424 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/sem_eval.adb')
-rw-r--r--gcc/ada/sem_eval.adb883
1 files changed, 589 insertions, 294 deletions
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
index c9054f387a8..0b324b65a40 100644
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -31,6 +31,7 @@ with Elists; use Elists;
with Errout; use Errout;
with Eval_Fat; use Eval_Fat;
with Exp_Util; use Exp_Util;
+with Freeze; use Freeze;
with Lib; use Lib;
with Namet; use Namet;
with Nmake; use Nmake;
@@ -126,6 +127,10 @@ package body Sem_Eval is
-- This is the actual cache, with entries consisting of node/value pairs,
-- and the impossible value Node_High_Bound used for unset entries.
+ type Range_Membership is (In_Range, Out_Of_Range, Unknown);
+ -- Range membership may either be statically known to be in range or out
+ -- of range, or not statically known. Used for Test_In_Range below.
+
-----------------------
-- Local Subprograms --
-----------------------
@@ -176,6 +181,15 @@ package body Sem_Eval is
-- used for producing the result of the static evaluation of the
-- logical operators
+ function Find_Universal_Operator_Type (N : Node_Id) return Entity_Id;
+ -- Check whether an arithmetic operation with universal operands which
+ -- is a rewritten function call with an explicit scope indication is
+ -- ambiguous: P."+" (1, 2) will be ambiguous if there is more than one
+ -- visible numeric type declared in P and the context does not impose a
+ -- type on the result (e.g. in the expression of a type conversion).
+ -- If ambiguous, emit an error and return Empty, else return the result
+ -- type of the operator.
+
procedure Test_Expression_Is_Foldable
(N : Node_Id;
Op1 : Node_Id;
@@ -210,6 +224,18 @@ package body Sem_Eval is
-- Same processing, except applies to an expression N with two operands
-- Op1 and Op2.
+ function Test_In_Range
+ (N : Node_Id;
+ Typ : Entity_Id;
+ Assume_Valid : Boolean;
+ Fixed_Int : Boolean;
+ Int_Real : Boolean) return Range_Membership;
+ -- Common processing for Is_In_Range and Is_Out_Of_Range:
+ -- Returns In_Range or Out_Of_Range if it can be guaranteed at compile time
+ -- that expression N is known to be in or out of range of the subtype Typ.
+ -- If not compile time known, Unknown is returned.
+ -- See documentation of Is_In_Range for complete description of parameters.
+
procedure To_Bits (U : Uint; B : out Bits);
-- Converts a Uint value to a bit string of length B'Length
@@ -616,9 +642,17 @@ package body Sem_Eval is
-- types, since we may have two NaN values and they should never
-- compare equal.
+ -- If the entity is a discriminant, the two expressions may be bounds
+ -- of components of objects of the same discriminated type. The
+ -- values of the discriminants are not static, and therefore the
+ -- result is unknown.
+
+ -- It would be better to comment individual branches of this test ???
+
if Nkind_In (Lf, N_Identifier, N_Expanded_Name)
and then Nkind_In (Rf, N_Identifier, N_Expanded_Name)
and then Entity (Lf) = Entity (Rf)
+ and then Ekind (Entity (Lf)) /= E_Discriminant
and then Present (Entity (Lf))
and then not Is_Floating_Point_Type (Etype (L))
and then not Is_Volatile_Reference (L)
@@ -1430,6 +1464,7 @@ package body Sem_Eval is
Right : constant Node_Id := Right_Opnd (N);
Ltype : constant Entity_Id := Etype (Left);
Rtype : constant Entity_Id := Etype (Right);
+ Otype : Entity_Id := Empty;
Stat : Boolean;
Fold : Boolean;
@@ -1442,6 +1477,13 @@ package body Sem_Eval is
return;
end if;
+ if Is_Universal_Numeric_Type (Etype (Left))
+ and then
+ Is_Universal_Numeric_Type (Etype (Right))
+ then
+ Otype := Find_Universal_Operator_Type (N);
+ end if;
+
-- Fold for cases where both operands are of integer type
if Is_Integer_Type (Ltype) and then Is_Integer_Type (Rtype) then
@@ -1548,9 +1590,9 @@ package body Sem_Eval is
Fold_Uint (N, Result, Stat);
end;
- -- Cases where at least one operand is a real. We handle the cases
- -- of both reals, or mixed/real integer cases (the latter happen
- -- only for divide and multiply, and the result is always real).
+ -- Cases where at least one operand is a real. We handle the cases of
+ -- both reals, or mixed/real integer cases (the latter happen only for
+ -- divide and multiply, and the result is always real).
elsif Is_Real_Type (Ltype) or else Is_Real_Type (Rtype) then
declare
@@ -1593,6 +1635,14 @@ package body Sem_Eval is
Fold_Ureal (N, Result, Stat);
end;
end if;
+
+ -- If the operator was resolved to a specific type, make sure that type
+ -- is frozen even if the expression is folded into a literal (which has
+ -- a universal type).
+
+ if Present (Otype) then
+ Freeze_Before (N, Otype);
+ end if;
end Eval_Arithmetic_Op;
----------------------------
@@ -1632,10 +1682,7 @@ package body Sem_Eval is
and then Present (Alias (Entity (Name (N))))
and then Is_Enumeration_Type (Base_Type (Typ))
then
- Lit := Alias (Entity (Name (N)));
- while Present (Alias (Lit)) loop
- Lit := Alias (Lit);
- end loop;
+ Lit := Ultimate_Alias (Entity (Name (N)));
if Ekind (Lit) = E_Enumeration_Literal then
if Base_Type (Etype (Lit)) /= Base_Type (Typ) then
@@ -1650,6 +1697,27 @@ package body Sem_Eval is
end if;
end Eval_Call;
+ --------------------------
+ -- Eval_Case_Expression --
+ --------------------------
+
+ -- Right now we do not attempt folding of any case expressions, and the
+ -- language does not require it, so the only required processing is to
+ -- do the check for all expressions appearing in the case expression.
+
+ procedure Eval_Case_Expression (N : Node_Id) is
+ Alt : Node_Id;
+
+ begin
+ Check_Non_Static_Context (Expression (N));
+
+ Alt := First (Alternatives (N));
+ while Present (Alt) loop
+ Check_Non_Static_Context (Expression (Alt));
+ Next (Alt);
+ end loop;
+ end Eval_Case_Expression;
+
------------------------
-- Eval_Concatenation --
------------------------
@@ -1767,18 +1835,79 @@ package body Sem_Eval is
-- Eval_Conditional_Expression --
---------------------------------
- -- This GNAT internal construct can never be statically folded, so the
- -- only required processing is to do the check for non-static context
- -- for the two expression operands.
+ -- We can fold to a static expression if the condition and both constituent
+ -- expressions are static. Otherwise, the only required processing is to do
+ -- the check for non-static context for the then and else expressions.
procedure Eval_Conditional_Expression (N : Node_Id) is
- Condition : constant Node_Id := First (Expressions (N));
- Then_Expr : constant Node_Id := Next (Condition);
- Else_Expr : constant Node_Id := Next (Then_Expr);
+ Condition : constant Node_Id := First (Expressions (N));
+ Then_Expr : constant Node_Id := Next (Condition);
+ Else_Expr : constant Node_Id := Next (Then_Expr);
+ Result : Node_Id;
+ Non_Result : Node_Id;
+
+ Rstat : constant Boolean :=
+ Is_Static_Expression (Condition)
+ and then
+ Is_Static_Expression (Then_Expr)
+ and then
+ Is_Static_Expression (Else_Expr);
begin
- Check_Non_Static_Context (Then_Expr);
- Check_Non_Static_Context (Else_Expr);
+ -- If any operand is Any_Type, just propagate to result and do not try
+ -- to fold, this prevents cascaded errors.
+
+ if Etype (Condition) = Any_Type or else
+ Etype (Then_Expr) = Any_Type or else
+ Etype (Else_Expr) = Any_Type
+ then
+ Set_Etype (N, Any_Type);
+ Set_Is_Static_Expression (N, False);
+ return;
+
+ -- Static case where we can fold. Note that we don't try to fold cases
+ -- where the condition is known at compile time, but the result is
+ -- non-static. This avoids possible cases of infinite recursion where
+ -- the expander puts in a redundant test and we remove it. Instead we
+ -- deal with these cases in the expander.
+
+ elsif Rstat then
+
+ -- Select result operand
+
+ if Is_True (Expr_Value (Condition)) then
+ Result := Then_Expr;
+ Non_Result := Else_Expr;
+ else
+ Result := Else_Expr;
+ Non_Result := Then_Expr;
+ end if;
+
+ -- Note that it does not matter if the non-result operand raises a
+ -- Constraint_Error, but if the result raises constraint error then
+ -- we replace the node with a raise constraint error. This will
+ -- properly propagate Raises_Constraint_Error since this flag is
+ -- set in Result.
+
+ if Raises_Constraint_Error (Result) then
+ Rewrite_In_Raise_CE (N, Result);
+ Check_Non_Static_Context (Non_Result);
+
+ -- Otherwise the result operand replaces the original node
+
+ else
+ Rewrite (N, Relocate_Node (Result));
+ end if;
+
+ -- Case of condition not known at compile time
+
+ else
+ Check_Non_Static_Context (Condition);
+ Check_Non_Static_Context (Then_Expr);
+ Check_Non_Static_Context (Else_Expr);
+ end if;
+
+ Set_Is_Static_Expression (N, Rstat);
end Eval_Conditional_Expression;
----------------------
@@ -2069,7 +2198,11 @@ package body Sem_Eval is
Right_Int : constant Uint := Expr_Value (Right);
begin
- if Is_Modular_Integer_Type (Etype (N)) then
+ -- VMS includes bitwise operations on signed types
+
+ if Is_Modular_Integer_Type (Etype (N))
+ or else Is_VMS_Operator (Entity (N))
+ then
declare
Left_Bits : Bits (0 .. UI_To_Int (Esize (Etype (N))) - 1);
Right_Bits : Bits (0 .. UI_To_Int (Esize (Etype (N))) - 1);
@@ -2144,9 +2277,7 @@ package body Sem_Eval is
-- Ignore if error in either operand, except to make sure that Any_Type
-- is properly propagated to avoid junk cascaded errors.
- if Etype (Left) = Any_Type
- or else Etype (Right) = Any_Type
- then
+ if Etype (Left) = Any_Type or else Etype (Right) = Any_Type then
Set_Etype (N, Any_Type);
return;
end if;
@@ -2219,7 +2350,8 @@ package body Sem_Eval is
declare
Typlen : constant Uint := String_Type_Len (Etype (Right));
Strlen : constant Uint :=
- UI_From_Int (String_Length (Strval (Get_String_Val (Left))));
+ UI_From_Int
+ (String_Length (Strval (Get_String_Val (Left))));
begin
Result := (Typlen = Strlen);
end;
@@ -2252,6 +2384,7 @@ package body Sem_Eval is
end if;
Fold_Uint (N, Test (Result), True);
+
Warn_On_Known_Condition (N);
end Eval_Membership_Op;
@@ -2311,8 +2444,8 @@ package body Sem_Eval is
Result : Uint;
begin
- -- Exponentiation of an integer raises the exception
- -- Constraint_Error for a negative exponent (RM 4.5.6)
+ -- Exponentiation of an integer raises Constraint_Error for a
+ -- negative exponent (RM 4.5.6).
if Right_Int < 0 then
Apply_Compile_Time_Constraint_Error
@@ -2427,9 +2560,9 @@ package body Sem_Eval is
begin
-- Can only fold if target is string or scalar and subtype is static.
- -- Also, do not fold if our parent is an allocator (this is because
- -- the qualified expression is really part of the syntactic structure
- -- of an allocator, and we do not want to end up with something that
+ -- Also, do not fold if our parent is an allocator (this is because the
+ -- qualified expression is really part of the syntactic structure of an
+ -- allocator, and we do not want to end up with something that
-- corresponds to "new 1" where the 1 is the result of folding a
-- qualified expression).
@@ -2529,14 +2662,15 @@ package body Sem_Eval is
-- Eval_Relational_Op --
------------------------
- -- Relational operations are static functions, so the result is static
- -- if both operands are static (RM 4.9(7), 4.9(20)), except that for
- -- strings, the result is never static, even if the operands are.
+ -- Relational operations are static functions, so the result is static if
+ -- both operands are static (RM 4.9(7), 4.9(20)), except that for strings,
+ -- the result is never static, even if the operands are.
procedure Eval_Relational_Op (N : Node_Id) is
Left : constant Node_Id := Left_Opnd (N);
Right : constant Node_Id := Right_Opnd (N);
Typ : constant Entity_Id := Etype (Left);
+ Otype : Entity_Id := Empty;
Result : Boolean;
Stat : Boolean;
Fold : Boolean;
@@ -2615,7 +2749,7 @@ package body Sem_Eval is
-- entity name, and the two X's are the same and K1 and K2 are
-- known at compile time, in this case, the length can also be
-- computed at compile time, even though the bounds are not
- -- known. A common case of this is e.g. (X'First..X'First+5).
+ -- known. A common case of this is e.g. (X'First .. X'First+5).
Extract_Length : declare
procedure Decompose_Expr
@@ -2645,17 +2779,37 @@ package body Sem_Eval is
if Nkind (Expr) = N_Op_Add
and then Compile_Time_Known_Value (Right_Opnd (Expr))
then
- Exp := Left_Opnd (Expr);
+ Exp := Left_Opnd (Expr);
Cons := Expr_Value (Right_Opnd (Expr));
elsif Nkind (Expr) = N_Op_Subtract
and then Compile_Time_Known_Value (Right_Opnd (Expr))
then
- Exp := Left_Opnd (Expr);
+ Exp := Left_Opnd (Expr);
Cons := -Expr_Value (Right_Opnd (Expr));
+ -- If the bound is a constant created to remove side
+ -- effects, recover original expression to see if it has
+ -- one of the recognizable forms.
+
+ elsif Nkind (Expr) = N_Identifier
+ and then not Comes_From_Source (Entity (Expr))
+ and then Ekind (Entity (Expr)) = E_Constant
+ and then
+ Nkind (Parent (Entity (Expr))) = N_Object_Declaration
+ then
+ Exp := Expression (Parent (Entity (Expr)));
+ Decompose_Expr (Exp, Ent, Kind, Cons);
+
+ -- If original expression includes an entity, create a
+ -- reference to it for use below.
+
+ if Present (Ent) then
+ Exp := New_Occurrence_Of (Ent, Sloc (Ent));
+ end if;
+
else
- Exp := Expr;
+ Exp := Expr;
Cons := Uint_0;
end if;
@@ -2664,8 +2818,10 @@ package body Sem_Eval is
if Nkind (Exp) = N_Attribute_Reference then
if Attribute_Name (Exp) = Name_First then
Kind := 'F';
+
elsif Attribute_Name (Exp) = Name_Last then
Kind := 'L';
+
else
Ent := Empty;
return;
@@ -2746,6 +2902,17 @@ package body Sem_Eval is
Set_Is_Static_Expression (N, False);
end if;
+ -- For operators on universal numeric types called as functions with
+ -- an explicit scope, determine appropriate specific numeric type, and
+ -- diagnose possible ambiguity.
+
+ if Is_Universal_Numeric_Type (Etype (Left))
+ and then
+ Is_Universal_Numeric_Type (Etype (Right))
+ then
+ Otype := Find_Universal_Operator_Type (N);
+ end if;
+
-- For static real type expressions, we cannot use Compile_Time_Compare
-- since it worries about run-time results which are not exact.
@@ -2845,6 +3012,13 @@ package body Sem_Eval is
Fold_Uint (N, Test (Result), Stat);
end if;
+ -- For the case of a folded relational operator on a specific numeric
+ -- type, freeze operand type now.
+
+ if Present (Otype) then
+ Freeze_Before (N, Otype);
+ end if;
+
Warn_On_Known_Condition (N);
end Eval_Relational_Op;
@@ -2852,9 +3026,9 @@ package body Sem_Eval is
-- Eval_Shift --
----------------
- -- Shift operations are intrinsic operations that can never be static,
- -- so the only processing required is to perform the required check for
- -- a non static context for the two operands.
+ -- Shift operations are intrinsic operations that can never be static, so
+ -- the only processing required is to perform the required check for a non
+ -- static context for the two operands.
-- Actually we could do some compile time evaluation here some time ???
@@ -2868,24 +3042,24 @@ package body Sem_Eval is
-- Eval_Short_Circuit --
------------------------
- -- A short circuit operation is potentially static if both operands
- -- are potentially static (RM 4.9 (13))
+ -- A short circuit operation is potentially static if both operands are
+ -- potentially static (RM 4.9 (13)).
procedure Eval_Short_Circuit (N : Node_Id) is
Kind : constant Node_Kind := Nkind (N);
Left : constant Node_Id := Left_Opnd (N);
Right : constant Node_Id := Right_Opnd (N);
Left_Int : Uint;
- Rstat : constant Boolean :=
- Is_Static_Expression (Left)
- and then Is_Static_Expression (Right);
+
+ Rstat : constant Boolean :=
+ Is_Static_Expression (Left)
+ and then
+ Is_Static_Expression (Right);
begin
-- Short circuit operations are never static in Ada 83
- if Ada_Version = Ada_83
- and then Comes_From_Source (N)
- then
+ if Ada_Version = Ada_83 and then Comes_From_Source (N) then
Check_Non_Static_Context (Left);
Check_Non_Static_Context (Right);
return;
@@ -2896,8 +3070,8 @@ package body Sem_Eval is
-- are a special case, they can still be foldable, even if the right
-- operand raises constraint error.
- -- If either operand is Any_Type, just propagate to result and
- -- do not try to fold, this prevents cascaded errors.
+ -- If either operand is Any_Type, just propagate to result and do not
+ -- try to fold, this prevents cascaded errors.
if Etype (Left) = Any_Type or else Etype (Right) = Any_Type then
Set_Etype (N, Any_Type);
@@ -2942,7 +3116,7 @@ package body Sem_Eval is
if (Kind = N_And_Then and then Is_False (Left_Int))
or else
- (Kind = N_Or_Else and then Is_True (Left_Int))
+ (Kind = N_Or_Else and then Is_True (Left_Int))
then
Fold_Uint (N, Left_Int, Rstat);
return;
@@ -2970,8 +3144,8 @@ package body Sem_Eval is
-- Eval_Slice --
----------------
- -- Slices can never be static, so the only processing required is to
- -- check for non-static context if an explicit range is given.
+ -- Slices can never be static, so the only processing required is to check
+ -- for non-static context if an explicit range is given.
procedure Eval_Slice (N : Node_Id) is
Drange : constant Node_Id := Discrete_Range (N);
@@ -2981,7 +3155,7 @@ package body Sem_Eval is
Check_Non_Static_Context (High_Bound (Drange));
end if;
- -- A slice of the form A (subtype), when the subtype is the index of
+ -- A slice of the form A (subtype), when the subtype is the index of
-- the type of A, is redundant, the slice can be replaced with A, and
-- this is worth a warning.
@@ -3002,7 +3176,7 @@ package body Sem_Eval is
Error_Msg_N ("redundant slice denotes whole array?", N);
end if;
- -- The following might be a useful optimization ????
+ -- The following might be a useful optimization????
-- Rewrite (N, New_Occurrence_Of (E, Sloc (N)));
end if;
@@ -3024,7 +3198,7 @@ package body Sem_Eval is
begin
-- Nothing to do if error type (handles cases like default expressions
- -- or generics where we have not yet fully resolved the type)
+ -- or generics where we have not yet fully resolved the type).
if Bas = Any_Type or else Bas = Any_String then
return;
@@ -3042,7 +3216,7 @@ package body Sem_Eval is
end if;
-- Here if Etype of string literal is normal Etype (not yet possible,
- -- but may be possible in future!)
+ -- but may be possible in future).
elsif not Is_OK_Static_Expression
(Type_Low_Bound (Etype (First_Index (Typ))))
@@ -3058,12 +3232,12 @@ package body Sem_Eval is
return;
end if;
- -- Test for illegal Ada 95 cases. A string literal is illegal in
- -- Ada 95 if its bounds are outside the index base type and this
- -- index type is static. This can happen in only two ways. Either
- -- the string literal is too long, or it is null, and the lower
- -- bound is type'First. In either case it is the upper bound that
- -- is out of range of the index type.
+ -- Test for illegal Ada 95 cases. A string literal is illegal in Ada 95
+ -- if its bounds are outside the index base type and this index type is
+ -- static. This can happen in only two ways. Either the string literal
+ -- is too long, or it is null, and the lower bound is type'First. In
+ -- either case it is the upper bound that is out of range of the index
+ -- type.
if Ada_Version >= Ada_95 then
if Root_Type (Bas) = Standard_String
@@ -3109,7 +3283,7 @@ package body Sem_Eval is
-- A type conversion is potentially static if its subtype mark is for a
-- static scalar subtype, and its operand expression is potentially static
- -- (RM 4.9 (10))
+ -- (RM 4.9(10)).
procedure Eval_Type_Conversion (N : Node_Id) is
Operand : constant Node_Id := Expression (N);
@@ -3120,9 +3294,9 @@ package body Sem_Eval is
Fold : Boolean;
function To_Be_Treated_As_Integer (T : Entity_Id) return Boolean;
- -- Returns true if type T is an integer type, or if it is a
- -- fixed-point type to be treated as an integer (i.e. the flag
- -- Conversion_OK is set on the conversion node).
+ -- Returns true if type T is an integer type, or if it is a fixed-point
+ -- type to be treated as an integer (i.e. the flag Conversion_OK is set
+ -- on the conversion node).
function To_Be_Treated_As_Real (T : Entity_Id) return Boolean;
-- Returns true if type T is a floating-point type, or if it is a
@@ -3256,10 +3430,11 @@ package body Sem_Eval is
-------------------
-- Predefined unary operators are static functions (RM 4.9(20)) and thus
- -- are potentially static if the operand is potentially static (RM 4.9(7))
+ -- are potentially static if the operand is potentially static (RM 4.9(7)).
procedure Eval_Unary_Op (N : Node_Id) is
Right : constant Node_Id := Right_Opnd (N);
+ Otype : Entity_Id := Empty;
Stat : Boolean;
Fold : Boolean;
@@ -3272,6 +3447,13 @@ package body Sem_Eval is
return;
end if;
+ if Etype (Right) = Universal_Integer
+ or else
+ Etype (Right) = Universal_Real
+ then
+ Otype := Find_Universal_Operator_Type (N);
+ end if;
+
-- Fold for integer case
if Is_Integer_Type (Etype (N)) then
@@ -3327,6 +3509,14 @@ package body Sem_Eval is
Fold_Ureal (N, Result, Stat);
end;
end if;
+
+ -- If the operator was resolved to a specific type, make sure that type
+ -- is frozen even if the expression is folded into a literal (which has
+ -- a universal type).
+
+ if Present (Otype) then
+ Freeze_Before (N, Otype);
+ end if;
end Eval_Unary_Op;
-------------------------------
@@ -3353,8 +3543,8 @@ package body Sem_Eval is
if Is_Entity_Name (N) then
Ent := Entity (N);
- -- An enumeration literal that was either in the source or
- -- created as a result of static evaluation.
+ -- An enumeration literal that was either in the source or created
+ -- as a result of static evaluation.
if Ekind (Ent) = E_Enumeration_Literal then
return Enumeration_Rep (Ent);
@@ -3366,8 +3556,8 @@ package body Sem_Eval is
return Expr_Rep_Value (Constant_Value (Ent));
end if;
- -- An integer literal that was either in the source or created
- -- as a result of static evaluation.
+ -- An integer literal that was either in the source or created as a
+ -- result of static evaluation.
elsif Kind = N_Integer_Literal then
return Intval (N);
@@ -3394,11 +3584,11 @@ package body Sem_Eval is
pragma Assert (Kind = N_Character_Literal);
Ent := Entity (N);
- -- Since Character literals of type Standard.Character don't
- -- have any defining character literals built for them, they
- -- do not have their Entity set, so just use their Char
- -- code. Otherwise for user-defined character literals use
- -- their Pos value as usual which is the same as the Rep value.
+ -- Since Character literals of type Standard.Character don't have any
+ -- defining character literals built for them, they do not have their
+ -- Entity set, so just use their Char code. Otherwise for user-
+ -- defined character literals use their Pos value as usual which is
+ -- the same as the Rep value.
if No (Ent) then
return Char_Literal_Value (N);
@@ -3432,8 +3622,8 @@ package body Sem_Eval is
if Is_Entity_Name (N) then
Ent := Entity (N);
- -- An enumeration literal that was either in the source or
- -- created as a result of static evaluation.
+ -- An enumeration literal that was either in the source or created as
+ -- a result of static evaluation.
if Ekind (Ent) = E_Enumeration_Literal then
Val := Enumeration_Pos (Ent);
@@ -3445,8 +3635,8 @@ package body Sem_Eval is
Val := Expr_Value (Constant_Value (Ent));
end if;
- -- An integer literal that was either in the source or created
- -- as a result of static evaluation.
+ -- An integer literal that was either in the source or created as a
+ -- result of static evaluation.
elsif Kind = N_Integer_Literal then
Val := Intval (N);
@@ -3558,8 +3748,8 @@ package body Sem_Eval is
return Ureal_0;
end if;
- -- If we fall through, we have a node that cannot be interpreted
- -- as a compile time constant. That is definitely an error.
+ -- If we fall through, we have a node that cannot be interpreted as a
+ -- compile time constant. That is definitely an error.
raise Program_Error;
end Expr_Value_R;
@@ -3578,6 +3768,144 @@ package body Sem_Eval is
end if;
end Expr_Value_S;
+ ----------------------------------
+ -- Find_Universal_Operator_Type --
+ ----------------------------------
+
+ function Find_Universal_Operator_Type (N : Node_Id) return Entity_Id is
+ PN : constant Node_Id := Parent (N);
+ Call : constant Node_Id := Original_Node (N);
+ Is_Int : constant Boolean := Is_Integer_Type (Etype (N));
+
+ Is_Fix : constant Boolean :=
+ Nkind (N) in N_Binary_Op
+ and then Nkind (Right_Opnd (N)) /= Nkind (Left_Opnd (N));
+ -- A mixed-mode operation in this context indicates the presence of
+ -- fixed-point type in the designated package.
+
+ Is_Relational : constant Boolean := Etype (N) = Standard_Boolean;
+ -- Case where N is a relational (or membership) operator (else it is an
+ -- arithmetic one).
+
+ In_Membership : constant Boolean :=
+ Nkind (PN) in N_Membership_Test
+ and then
+ Nkind (Right_Opnd (PN)) = N_Range
+ and then
+ Is_Universal_Numeric_Type (Etype (Left_Opnd (PN)))
+ and then
+ Is_Universal_Numeric_Type
+ (Etype (Low_Bound (Right_Opnd (PN))))
+ and then
+ Is_Universal_Numeric_Type
+ (Etype (High_Bound (Right_Opnd (PN))));
+ -- Case where N is part of a membership test with a universal range
+
+ E : Entity_Id;
+ Pack : Entity_Id;
+ Typ1 : Entity_Id := Empty;
+ Priv_E : Entity_Id;
+
+ function Is_Mixed_Mode_Operand (Op : Node_Id) return Boolean;
+ -- Check whether one operand is a mixed-mode operation that requires the
+ -- presence of a fixed-point type. Given that all operands are universal
+ -- and have been constant-folded, retrieve the original function call.
+
+ ---------------------------
+ -- Is_Mixed_Mode_Operand --
+ ---------------------------
+
+ function Is_Mixed_Mode_Operand (Op : Node_Id) return Boolean is
+ Onod : constant Node_Id := Original_Node (Op);
+ begin
+ return Nkind (Onod) = N_Function_Call
+ and then Present (Next_Actual (First_Actual (Onod)))
+ and then Etype (First_Actual (Onod)) /=
+ Etype (Next_Actual (First_Actual (Onod)));
+ end Is_Mixed_Mode_Operand;
+
+ -- Start of processing for Find_Universal_Operator_Type
+
+ begin
+ if Nkind (Call) /= N_Function_Call
+ or else Nkind (Name (Call)) /= N_Expanded_Name
+ then
+ return Empty;
+
+ -- There are several cases where the context does not imply the type of
+ -- the operands:
+ -- - the universal expression appears in a type conversion;
+ -- - the expression is a relational operator applied to universal
+ -- operands;
+ -- - the expression is a membership test with a universal operand
+ -- and a range with universal bounds.
+
+ elsif Nkind (Parent (N)) = N_Type_Conversion
+ or else Is_Relational
+ or else In_Membership
+ then
+ Pack := Entity (Prefix (Name (Call)));
+
+ -- If the prefix is a package declared elsewhere, iterate over its
+ -- visible entities, otherwise iterate over all declarations in the
+ -- designated scope.
+
+ if Ekind (Pack) = E_Package
+ and then not In_Open_Scopes (Pack)
+ then
+ Priv_E := First_Private_Entity (Pack);
+ else
+ Priv_E := Empty;
+ end if;
+
+ Typ1 := Empty;
+ E := First_Entity (Pack);
+ while Present (E) and then E /= Priv_E loop
+ if Is_Numeric_Type (E)
+ and then Nkind (Parent (E)) /= N_Subtype_Declaration
+ and then Comes_From_Source (E)
+ and then Is_Integer_Type (E) = Is_Int
+ and then
+ (Nkind (N) in N_Unary_Op
+ or else Is_Relational
+ or else Is_Fixed_Point_Type (E) = Is_Fix)
+ then
+ if No (Typ1) then
+ Typ1 := E;
+
+ -- Before emitting an error, check for the presence of a
+ -- mixed-mode operation that specifies a fixed point type.
+
+ elsif Is_Relational
+ and then
+ (Is_Mixed_Mode_Operand (Left_Opnd (N))
+ or else Is_Mixed_Mode_Operand (Right_Opnd (N)))
+ and then Is_Fixed_Point_Type (E) /= Is_Fixed_Point_Type (Typ1)
+
+ then
+ if Is_Fixed_Point_Type (E) then
+ Typ1 := E;
+ end if;
+
+ else
+ -- More than one type of the proper class declared in P
+
+ Error_Msg_N ("ambiguous operation", N);
+ Error_Msg_Sloc := Sloc (Typ1);
+ Error_Msg_N ("\possible interpretation (inherited)#", N);
+ Error_Msg_Sloc := Sloc (E);
+ Error_Msg_N ("\possible interpretation (inherited)#", N);
+ return Empty;
+ end if;
+ end if;
+
+ Next_Entity (E);
+ end loop;
+ end if;
+
+ return Typ1;
+ end Find_Universal_Operator_Type;
+
--------------------------
-- Flag_Non_Static_Expr --
--------------------------
@@ -3623,8 +3951,8 @@ package body Sem_Eval is
Ent : Entity_Id;
begin
- -- If we are folding a named number, retain the entity in the
- -- literal, for ASIS use.
+ -- If we are folding a named number, retain the entity in the literal,
+ -- for ASIS use.
if Is_Entity_Name (N)
and then Ekind (Entity (N)) = E_Named_Integer
@@ -3677,8 +4005,8 @@ package body Sem_Eval is
Ent : Entity_Id;
begin
- -- If we are folding a named number, retain the entity in the
- -- literal, for ASIS use.
+ -- If we are folding a named number, retain the entity in the literal,
+ -- for ASIS use.
if Is_Entity_Name (N)
and then Ekind (Entity (N)) = E_Named_Real
@@ -3872,78 +4200,9 @@ package body Sem_Eval is
Fixed_Int : Boolean := False;
Int_Real : Boolean := False) return Boolean
is
- Val : Uint;
- Valr : Ureal;
-
- pragma Warnings (Off, Assume_Valid);
- -- For now Assume_Valid is unreferenced since the current implementation
- -- always returns False if N is not a compile time known value, but we
- -- keep the parameter to allow for future enhancements in which we try
- -- to get the information in the variable case as well.
-
begin
- -- Universal types have no range limits, so always in range
-
- if Typ = Universal_Integer or else Typ = Universal_Real then
- return True;
-
- -- Never in range if not scalar type. Don't know if this can
- -- actually happen, but our spec allows it, so we must check!
-
- elsif not Is_Scalar_Type (Typ) then
- return False;
-
- -- Never in range unless we have a compile time known value
-
- elsif not Compile_Time_Known_Value (N) then
- return False;
-
- -- General processing with a known compile time value
-
- else
- declare
- Lo : Node_Id;
- Hi : Node_Id;
- LB_Known : Boolean;
- UB_Known : Boolean;
-
- begin
- Lo := Type_Low_Bound (Typ);
- Hi := Type_High_Bound (Typ);
-
- LB_Known := Compile_Time_Known_Value (Lo);
- UB_Known := Compile_Time_Known_Value (Hi);
-
- -- Fixed point types should be considered as such only in
- -- flag Fixed_Int is set to False.
-
- if Is_Floating_Point_Type (Typ)
- or else (Is_Fixed_Point_Type (Typ) and then not Fixed_Int)
- or else Int_Real
- then
- Valr := Expr_Value_R (N);
-
- if LB_Known and then Valr >= Expr_Value_R (Lo)
- and then UB_Known and then Valr <= Expr_Value_R (Hi)
- then
- return True;
- else
- return False;
- end if;
-
- else
- Val := Expr_Value (N);
-
- if LB_Known and then Val >= Expr_Value (Lo)
- and then UB_Known and then Val <= Expr_Value (Hi)
- then
- return True;
- else
- return False;
- end if;
- end if;
- end;
- end if;
+ return Test_In_Range (N, Typ, Assume_Valid, Fixed_Int, Int_Real)
+ = In_Range;
end Is_In_Range;
-------------------
@@ -3998,8 +4257,8 @@ package body Sem_Eval is
-- Is_OK_Static_Subtype --
--------------------------
- -- Determines if Typ is a static subtype as defined in (RM 4.9(26))
- -- where neither bound raises constraint error when evaluated.
+ -- Determines if Typ is a static subtype as defined in (RM 4.9(26)) where
+ -- neither bound raises constraint error when evaluated.
function Is_OK_Static_Subtype (Typ : Entity_Id) return Boolean is
Base_T : constant Entity_Id := Base_Type (Typ);
@@ -4041,8 +4300,8 @@ package body Sem_Eval is
return True;
else
- -- Scalar_Range (Typ) might be an N_Subtype_Indication, so
- -- use Get_Type_Low,High_Bound.
+ -- Scalar_Range (Typ) might be an N_Subtype_Indication, so use
+ -- Get_Type_{Low,High}_Bound.
return Is_OK_Static_Subtype (Anc_Subt)
and then Is_OK_Static_Expression (Type_Low_Bound (Typ))
@@ -4067,90 +4326,9 @@ package body Sem_Eval is
Fixed_Int : Boolean := False;
Int_Real : Boolean := False) return Boolean
is
- Val : Uint;
- Valr : Ureal;
-
- pragma Warnings (Off, Assume_Valid);
- -- For now Assume_Valid is unreferenced since the current implementation
- -- always returns False if N is not a compile time known value, but we
- -- keep the parameter to allow for future enhancements in which we try
- -- to get the information in the variable case as well.
-
begin
- -- Universal types have no range limits, so always in range
-
- if Typ = Universal_Integer or else Typ = Universal_Real then
- return False;
-
- -- Never out of range if not scalar type. Don't know if this can
- -- actually happen, but our spec allows it, so we must check!
-
- elsif not Is_Scalar_Type (Typ) then
- return False;
-
- -- Never out of range if this is a generic type, since the bounds
- -- of generic types are junk. Note that if we only checked for
- -- static expressions (instead of compile time known values) below,
- -- we would not need this check, because values of a generic type
- -- can never be static, but they can be known at compile time.
-
- elsif Is_Generic_Type (Typ) then
- return False;
-
- -- Never out of range unless we have a compile time known value
-
- elsif not Compile_Time_Known_Value (N) then
- return False;
-
- else
- declare
- Lo : Node_Id;
- Hi : Node_Id;
- LB_Known : Boolean;
- UB_Known : Boolean;
-
- begin
- Lo := Type_Low_Bound (Typ);
- Hi := Type_High_Bound (Typ);
-
- LB_Known := Compile_Time_Known_Value (Lo);
- UB_Known := Compile_Time_Known_Value (Hi);
-
- -- Real types (note that fixed-point types are not treated
- -- as being of a real type if the flag Fixed_Int is set,
- -- since in that case they are regarded as integer types).
-
- if Is_Floating_Point_Type (Typ)
- or else (Is_Fixed_Point_Type (Typ) and then not Fixed_Int)
- or else Int_Real
- then
- Valr := Expr_Value_R (N);
-
- if LB_Known and then Valr < Expr_Value_R (Lo) then
- return True;
-
- elsif UB_Known and then Expr_Value_R (Hi) < Valr then
- return True;
-
- else
- return False;
- end if;
-
- else
- Val := Expr_Value (N);
-
- if LB_Known and then Val < Expr_Value (Lo) then
- return True;
-
- elsif UB_Known and then Expr_Value (Hi) < Val then
- return True;
-
- else
- return False;
- end if;
- end if;
- end;
- end if;
+ return Test_In_Range (N, Typ, Assume_Valid, Fixed_Int, Int_Real)
+ = Out_Of_Range;
end Is_Out_Of_Range;
---------------------
@@ -4275,10 +4453,9 @@ package body Sem_Eval is
begin
-- If we have the static expression case, then this is an illegality
-- in Ada 95 mode, except that in an instance, we never generate an
- -- error (if the error is legitimate, it was already diagnosed in
- -- the template). The expression to compute the length of a packed
- -- array is attached to the array type itself, and deserves a separate
- -- message.
+ -- error (if the error is legitimate, it was already diagnosed in the
+ -- template). The expression to compute the length of a packed array is
+ -- attached to the array type itself, and deserves a separate message.
if Is_Static_Expression (N)
and then not In_Instance
@@ -4300,8 +4477,8 @@ package body Sem_Eval is
(N, "value not in range of}", CE_Range_Check_Failed);
end if;
- -- Here we generate a warning for the Ada 83 case, or when we are
- -- in an instance, or when we have a non-static expression case.
+ -- Here we generate a warning for the Ada 83 case, or when we are in an
+ -- instance, or when we have a non-static expression case.
else
Apply_Compile_Time_Constraint_Error
@@ -4317,22 +4494,22 @@ package body Sem_Eval is
Typ : constant Entity_Id := Etype (N);
begin
- -- If we want to raise CE in the condition of a raise_CE node
- -- we may as well get rid of the condition
+ -- If we want to raise CE in the condition of a N_Raise_CE node
+ -- we may as well get rid of the condition.
if Present (Parent (N))
and then Nkind (Parent (N)) = N_Raise_Constraint_Error
then
Set_Condition (Parent (N), Empty);
- -- If the expression raising CE is a N_Raise_CE node, we can use
- -- that one. We just preserve the type of the context
+ -- If the expression raising CE is a N_Raise_CE node, we can use that
+ -- one. We just preserve the type of the context.
elsif Nkind (Exp) = N_Raise_Constraint_Error then
Rewrite (N, Exp);
Set_Etype (N, Typ);
- -- We have to build an explicit raise_ce node
+ -- Else build an explcit N_Raise_CE
else
Rewrite (N,
@@ -4470,15 +4647,15 @@ package body Sem_Eval is
-- subtype, i.e. both types must be constrained or unconstrained.
-- To understand the requirement for this test, see RM 4.9.1(1).
- -- As is made clear in RM 3.5.4(11), type Integer, for example
- -- is a constrained subtype with constraint bounds matching the
- -- bounds of its corresponding unconstrained base type. In this
- -- situation, Integer and Integer'Base do not statically match,
- -- even though they have the same bounds.
+ -- As is made clear in RM 3.5.4(11), type Integer, for example is
+ -- a constrained subtype with constraint bounds matching the bounds
+ -- of its corresponding unconstrained base type. In this situation,
+ -- Integer and Integer'Base do not statically match, even though
+ -- they have the same bounds.
- -- We only apply this test to types in Standard and types that
- -- appear in user programs. That way, we do not have to be
- -- too careful about setting Is_Constrained right for itypes.
+ -- We only apply this test to types in Standard and types that appear
+ -- in user programs. That way, we do not have to be too careful about
+ -- setting Is_Constrained right for Itypes.
if Is_Numeric_Type (T1)
and then (Is_Constrained (T1) /= Is_Constrained (T2))
@@ -4489,9 +4666,9 @@ package body Sem_Eval is
then
return False;
- -- A generic scalar type does not statically match its base
- -- type (AI-311). In this case we make sure that the formals,
- -- which are first subtypes of their bases, are constrained.
+ -- A generic scalar type does not statically match its base type
+ -- (AI-311). In this case we make sure that the formals, which are
+ -- first subtypes of their bases, are constrained.
elsif Is_Generic_Type (T1)
and then Is_Generic_Type (T2)
@@ -4500,12 +4677,12 @@ package body Sem_Eval is
return False;
end if;
- -- If there was an error in either range, then just assume
- -- the types statically match to avoid further junk errors
+ -- If there was an error in either range, then just assume the types
+ -- statically match to avoid further junk errors.
- if Error_Posted (Scalar_Range (T1))
- or else
- Error_Posted (Scalar_Range (T2))
+ if No (Scalar_Range (T1)) or else No (Scalar_Range (T2))
+ or else Error_Posted (Scalar_Range (T1))
+ or else Error_Posted (Scalar_Range (T2))
then
return True;
end if;
@@ -4532,8 +4709,8 @@ package body Sem_Eval is
then
return False;
- -- If either type has constraint error bounds, then say
- -- that they match to avoid junk cascaded errors here.
+ -- If either type has constraint error bounds, then say that
+ -- they match to avoid junk cascaded errors here.
elsif not Is_OK_Static_Subtype (T1)
or else not Is_OK_Static_Subtype (T2)
@@ -4643,11 +4820,11 @@ package body Sem_Eval is
return True;
- -- A definite type does not match an indefinite or classwide type
+ -- A definite type does not match an indefinite or classwide type.
-- However, a generic type with unknown discriminants may be
-- instantiated with a type with no discriminants, and conformance
- -- checking on an inherited operation may compare the actual with
- -- the subtype that renames it in the instance.
+ -- checking on an inherited operation may compare the actual with the
+ -- subtype that renames it in the instance.
elsif
Has_Unknown_Discriminants (T1) /= Has_Unknown_Discriminants (T2)
@@ -4659,16 +4836,15 @@ package body Sem_Eval is
elsif Is_Array_Type (T1) then
- -- If either subtype is unconstrained then both must be,
- -- and if both are unconstrained then no further checking
- -- is needed.
+ -- If either subtype is unconstrained then both must be, and if both
+ -- are unconstrained then no further checking is neede.
if not Is_Constrained (T1) or else not Is_Constrained (T2) then
return not (Is_Constrained (T1) or else Is_Constrained (T2));
end if;
- -- Both subtypes are constrained, so check that the index
- -- subtypes statically match.
+ -- Both subtypes are constrained, so check that the index subtypes
+ -- statically match.
declare
Index1 : Node_Id := First_Index (T1);
@@ -4693,8 +4869,8 @@ package body Sem_Eval is
if Can_Never_Be_Null (T1) /= Can_Never_Be_Null (T2) then
return False;
- elsif Ekind (T1) = E_Access_Subprogram_Type
- or else Ekind (T1) = E_Anonymous_Access_Subprogram_Type
+ elsif Ekind_In (T1, E_Access_Subprogram_Type,
+ E_Anonymous_Access_Subprogram_Type)
then
return
Subtype_Conformant
@@ -4819,8 +4995,8 @@ package body Sem_Eval is
Set_Etype (N, Any_Type);
return;
- -- If left operand raises constraint error, then replace node N with
- -- the raise constraint error node, and we are obviously not foldable.
+ -- If left operand raises constraint error, then replace node N with the
+ -- Raise_Constraint_Error node, and we are obviously not foldable.
-- Is_Static_Expression is set from the two operands in the normal way,
-- and we check the right operand if it is in a non-static context.
@@ -4833,9 +5009,9 @@ package body Sem_Eval is
Set_Is_Static_Expression (N, Rstat);
return;
- -- Similar processing for the case of the right operand. Note that
- -- we don't use this routine for the short-circuit case, so we do
- -- not have to worry about that special case here.
+ -- Similar processing for the case of the right operand. Note that we
+ -- don't use this routine for the short-circuit case, so we do not have
+ -- to worry about that special case here.
elsif Raises_Constraint_Error (Op2) then
if not Rstat then
@@ -4855,7 +5031,7 @@ package body Sem_Eval is
return;
-- If result is not static, then check non-static contexts on operands
- -- since one of them may be static and the other one may not be static
+ -- since one of them may be static and the other one may not be static.
elsif not Rstat then
Check_Non_Static_Context (Op1);
@@ -4864,8 +5040,8 @@ package body Sem_Eval is
and then Compile_Time_Known_Value (Op2);
return;
- -- Else result is static and foldable. Both operands are static,
- -- and neither raises constraint error, so we can definitely fold.
+ -- Else result is static and foldable. Both operands are static, and
+ -- neither raises constraint error, so we can definitely fold.
else
Set_Is_Static_Expression (N);
@@ -4875,6 +5051,125 @@ package body Sem_Eval is
end if;
end Test_Expression_Is_Foldable;
+ -------------------
+ -- Test_In_Range --
+ -------------------
+
+ function Test_In_Range
+ (N : Node_Id;
+ Typ : Entity_Id;
+ Assume_Valid : Boolean;
+ Fixed_Int : Boolean;
+ Int_Real : Boolean) return Range_Membership
+ is
+ Val : Uint;
+ Valr : Ureal;
+
+ pragma Warnings (Off, Assume_Valid);
+ -- For now Assume_Valid is unreferenced since the current implementation
+ -- always returns Unknown if N is not a compile time known value, but we
+ -- keep the parameter to allow for future enhancements in which we try
+ -- to get the information in the variable case as well.
+
+ begin
+ -- Universal types have no range limits, so always in range
+
+ if Typ = Universal_Integer or else Typ = Universal_Real then
+ return In_Range;
+
+ -- Never known if not scalar type. Don't know if this can actually
+ -- happen, but our spec allows it, so we must check!
+
+ elsif not Is_Scalar_Type (Typ) then
+ return Unknown;
+
+ -- Never known if this is a generic type, since the bounds of generic
+ -- types are junk. Note that if we only checked for static expressions
+ -- (instead of compile time known values) below, we would not need this
+ -- check, because values of a generic type can never be static, but they
+ -- can be known at compile time.
+
+ elsif Is_Generic_Type (Typ) then
+ return Unknown;
+
+ -- Never known unless we have a compile time known value
+
+ elsif not Compile_Time_Known_Value (N) then
+ return Unknown;
+
+ -- General processing with a known compile time value
+
+ else
+ declare
+ Lo : Node_Id;
+ Hi : Node_Id;
+
+ LB_Known : Boolean;
+ HB_Known : Boolean;
+
+ begin
+ Lo := Type_Low_Bound (Typ);
+ Hi := Type_High_Bound (Typ);
+
+ LB_Known := Compile_Time_Known_Value (Lo);
+ HB_Known := Compile_Time_Known_Value (Hi);
+
+ -- Fixed point types should be considered as such only if flag
+ -- Fixed_Int is set to False.
+
+ if Is_Floating_Point_Type (Typ)
+ or else (Is_Fixed_Point_Type (Typ) and then not Fixed_Int)
+ or else Int_Real
+ then
+ Valr := Expr_Value_R (N);
+
+ if LB_Known and HB_Known then
+ if Valr >= Expr_Value_R (Lo)
+ and then
+ Valr <= Expr_Value_R (Hi)
+ then
+ return In_Range;
+ else
+ return Out_Of_Range;
+ end if;
+
+ elsif (LB_Known and then Valr < Expr_Value_R (Lo))
+ or else
+ (HB_Known and then Valr > Expr_Value_R (Hi))
+ then
+ return Out_Of_Range;
+
+ else
+ return Unknown;
+ end if;
+
+ else
+ Val := Expr_Value (N);
+
+ if LB_Known and HB_Known then
+ if Val >= Expr_Value (Lo)
+ and then
+ Val <= Expr_Value (Hi)
+ then
+ return In_Range;
+ else
+ return Out_Of_Range;
+ end if;
+
+ elsif (LB_Known and then Val < Expr_Value (Lo))
+ or else
+ (HB_Known and then Val > Expr_Value (Hi))
+ then
+ return Out_Of_Range;
+
+ else
+ return Unknown;
+ end if;
+ end if;
+ end;
+ end if;
+ end Test_In_Range;
+
--------------
-- To_Bits --
--------------
@@ -4896,8 +5191,8 @@ package body Sem_Eval is
E : Entity_Id;
procedure Why_Not_Static_List (L : List_Id);
- -- A version that can be called on a list of expressions. Finds
- -- all non-static violations in any element of the list.
+ -- A version that can be called on a list of expressions. Finds all
+ -- non-static violations in any element of the list.
-------------------------
-- Why_Not_Static_List --
@@ -4919,8 +5214,8 @@ package body Sem_Eval is
-- Start of processing for Why_Not_Static
begin
- -- If in ACATS mode (debug flag 2), then suppress all these
- -- messages, this avoids massive updates to the ACATS base line.
+ -- If in ACATS mode (debug flag 2), then suppress all these messages,
+ -- this avoids massive updates to the ACATS base line.
if Debug_Flag_2 then
return;
@@ -5044,8 +5339,8 @@ package body Sem_Eval is
return;
- -- Special case generic types, since again this is a common
- -- source of confusion.
+ -- Special case generic types, since again this is a common source
+ -- of confusion.
elsif Is_Generic_Actual_Type (E)
or else