summaryrefslogtreecommitdiff
path: root/gcc/ada/sem_eval.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_eval.adb')
-rw-r--r--gcc/ada/sem_eval.adb649
1 files changed, 542 insertions, 107 deletions
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
index 92bf0a14199..cc6d6f3d79f 100644
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -1,4 +1,4 @@
----------------------
+------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2002 Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2003 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- --
@@ -209,23 +209,42 @@ package body Sem_Eval is
------------------------------
procedure Check_Non_Static_Context (N : Node_Id) is
- T : Entity_Id := Etype (N);
- Checks_On : constant Boolean :=
+ T : constant Entity_Id := Etype (N);
+ Checks_On : constant Boolean :=
not Index_Checks_Suppressed (T)
and not Range_Checks_Suppressed (T);
begin
- -- We need the check only for static expressions not raising CE
- -- We can also ignore cases in which the type is Any_Type
+ -- Ignore cases of non-scalar types or error types
- if not Is_OK_Static_Expression (N)
- or else Etype (N) = Any_Type
- then
+ if T = Any_Type or else not Is_Scalar_Type (T) then
return;
+ end if;
- -- Skip this check for non-scalar expressions
+ -- At this stage we have a scalar type. If we have an expression
+ -- that raises CE, then we already issued a warning or error msg
+ -- so there is nothing more to be done in this routine.
+
+ if Raises_Constraint_Error (N) then
+ return;
+ end if;
+
+ -- Now we have a scalar type which is not marked as raising a
+ -- constraint error exception. The main purpose of this routine
+ -- is to deal with static expressions appearing in a non-static
+ -- context. That means that if we do not have a static expression
+ -- then there is not much to do. The one case that we deal with
+ -- here is that if we have a floating-point value that is out of
+ -- range, then we post a warning that an infinity will result.
+
+ if not Is_Static_Expression (N) then
+ if Is_Floating_Point_Type (T)
+ and then Is_Out_Of_Range (N, Base_Type (T))
+ then
+ Error_Msg_N
+ ("?float value out of range, infinity will be generated", N);
+ end if;
- elsif not Is_Scalar_Type (T) then
return;
end if;
@@ -265,21 +284,16 @@ package body Sem_Eval is
(N, Corresponding_Integer_Value (N) * Small_Value (T));
elsif not UR_Is_Zero (Realval (N)) then
- declare
- RT : constant Entity_Id := Base_Type (T);
- X : constant Ureal := Machine (RT, Realval (N), Round);
- begin
- -- Warn if result of static rounding actually differs from
- -- runtime evaluation, which uses round to even.
+ -- Note: even though RM 4.9(38) specifies biased rounding,
+ -- this has been modified by AI-100 in order to prevent
+ -- confusing differences in rounding between static and
+ -- non-static expressions. AI-100 specifies that the effect
+ -- of such rounding is implementation dependent, and in GNAT
+ -- we round to nearest even to match the run-time behavior.
- if Warn_On_Biased_Rounding and Rounding_Was_Biased then
- Error_Msg_N ("static expression does not round to even"
- & " ('R'M 4.9(38))?", N);
- end if;
-
- Set_Realval (N, X);
- end;
+ Set_Realval
+ (N, Machine (Base_Type (T), Realval (N), Round_Even, N));
end if;
Set_Is_Machine_Number (N);
@@ -361,7 +375,11 @@ package body Sem_Eval is
-- Compile_Time_Compare --
--------------------------
- function Compile_Time_Compare (L, R : Node_Id) return Compare_Result is
+ function Compile_Time_Compare
+ (L, R : Node_Id;
+ Rec : Boolean := False)
+ return Compare_Result
+ is
Ltyp : constant Entity_Id := Etype (L);
Rtyp : constant Entity_Id := Etype (R);
@@ -518,12 +536,47 @@ package body Sem_Eval is
Lf : constant Node_Id := Compare_Fixup (L);
Rf : constant Node_Id := Compare_Fixup (R);
+ function Is_Same_Subscript (L, R : List_Id) return Boolean;
+ -- L, R are the Expressions values from two attribute nodes
+ -- for First or Last attributes. Either may be set to No_List
+ -- if no expressions are present (indicating subscript 1).
+ -- The result is True if both expressions represent the same
+ -- subscript (note that one case is where one subscript is
+ -- missing and the other is explicitly set to 1).
+
+ -----------------------
+ -- Is_Same_Subscript --
+ -----------------------
+
+ function Is_Same_Subscript (L, R : List_Id) return Boolean is
+ begin
+ if L = No_List then
+ if R = No_List then
+ return True;
+ else
+ return Expr_Value (First (R)) = Uint_1;
+ end if;
+
+ else
+ if R = No_List then
+ return Expr_Value (First (L)) = Uint_1;
+ else
+ return Expr_Value (First (L)) = Expr_Value (First (R));
+ end if;
+ end if;
+ end Is_Same_Subscript;
+
+ -- Start of processing for Is_Same_Value
+
begin
-- Values are the same if they are the same identifier and the
- -- identifier refers to a constant object (E_Constant)
+ -- identifier refers to a constant object (E_Constant). This
+ -- does not however apply to Float types, since we may have two
+ -- NaN values and they should never compare equal.
if Nkind (Lf) = N_Identifier and then Nkind (Rf) = N_Identifier
and then Entity (Lf) = Entity (Rf)
+ and then not Is_Floating_Point_Type (Etype (L))
and then (Ekind (Entity (Lf)) = E_Constant or else
Ekind (Entity (Lf)) = E_In_Parameter or else
Ekind (Entity (Lf)) = E_Loop_Parameter)
@@ -552,6 +605,7 @@ package body Sem_Eval is
and then Is_Entity_Name (Prefix (Lf))
and then Is_Entity_Name (Prefix (Rf))
and then Entity (Prefix (Lf)) = Entity (Prefix (Rf))
+ and then Is_Same_Subscript (Expressions (Lf), Expressions (Rf))
then
return True;
@@ -588,7 +642,9 @@ package body Sem_Eval is
elsif No (Ltyp) or else No (Rtyp) then
return Unknown;
- -- We only attempt compile time analysis for scalar values
+ -- We only attempt compile time analysis for scalar values, and
+ -- not for packed arrays represented as modular types, where the
+ -- semantics of comparison is quite different.
elsif not Is_Scalar_Type (Ltyp)
or else Is_Packed_Array_Type (Ltyp)
@@ -655,22 +711,46 @@ package body Sem_Eval is
-- attempt this optimization with generic types, since the type
-- bounds may not be meaningful in this case.
- if Is_Discrete_Type (Ltyp)
+ -- We are in danger of an infinite recursion here. It does not seem
+ -- useful to go more than one level deep, so the parameter Rec is
+ -- used to protect ourselves against this infinite recursion.
+
+ if not Rec
+ and then Is_Discrete_Type (Ltyp)
+ and then Is_Discrete_Type (Rtyp)
and then not Is_Generic_Type (Ltyp)
and then not Is_Generic_Type (Rtyp)
then
- if Is_Same_Value (R, Type_High_Bound (Ltyp)) then
- return LE;
+ -- See if we can get a decisive check against one operand and
+ -- a bound of the other operand (four possible tests here).
+
+ case Compile_Time_Compare (L, Type_Low_Bound (Rtyp), True) is
+ when LT => return LT;
+ when LE => return LE;
+ when EQ => return LE;
+ when others => null;
+ end case;
- elsif Is_Same_Value (R, Type_Low_Bound (Ltyp)) then
- return GE;
+ case Compile_Time_Compare (L, Type_High_Bound (Rtyp), True) is
+ when GT => return GT;
+ when GE => return GE;
+ when EQ => return GE;
+ when others => null;
+ end case;
- elsif Is_Same_Value (L, Type_High_Bound (Rtyp)) then
- return GE;
+ case Compile_Time_Compare (Type_Low_Bound (Ltyp), R, True) is
+ when GT => return GT;
+ when GE => return GE;
+ when EQ => return GE;
+ when others => null;
+ end case;
- elsif Is_Same_Value (L, Type_Low_Bound (Ltyp)) then
- return LE;
- end if;
+ case Compile_Time_Compare (Type_High_Bound (Ltyp), R, True) is
+ when LT => return LT;
+ when LE => return LE;
+ when EQ => return LE;
+ when others => null;
+ end case;
end if;
-- Next attempt is to decompose the expressions to extract
@@ -735,6 +815,17 @@ package body Sem_Eval is
return False;
end if;
+ -- If this is not a static expression and we are in configurable run
+ -- time mode, then we consider it not known at compile time. This
+ -- avoids anomalies where whether something is permitted with a given
+ -- configurable run-time library depends on how good the compiler is
+ -- at optimizing and knowing that things are constant when they
+ -- are non-static.
+
+ if Configurable_Run_Time_Mode and then not Is_Static_Expression (Op) then
+ return False;
+ end if;
+
-- If we have an entity name, then see if it is the name of a constant
-- and if so, test the corresponding constant value, or the name of
-- an enumeration literal, which is always a constant.
@@ -976,8 +1067,11 @@ package body Sem_Eval is
if Right_Int = 0 then
Apply_Compile_Time_Constraint_Error
- (N, "division by zero", CE_Divide_By_Zero);
+ (N, "division by zero",
+ CE_Divide_By_Zero,
+ Warn => not Stat);
return;
+
else
Result := Left_Int / Right_Int;
end if;
@@ -989,7 +1083,9 @@ package body Sem_Eval is
if Right_Int = 0 then
Apply_Compile_Time_Constraint_Error
- (N, "mod with zero divisor", CE_Divide_By_Zero);
+ (N, "mod with zero divisor",
+ CE_Divide_By_Zero,
+ Warn => not Stat);
return;
else
Result := Left_Int mod Right_Int;
@@ -1002,8 +1098,11 @@ package body Sem_Eval is
if Right_Int = 0 then
Apply_Compile_Time_Constraint_Error
- (N, "rem with zero divisor", CE_Divide_By_Zero);
+ (N, "rem with zero divisor",
+ CE_Divide_By_Zero,
+ Warn => not Stat);
return;
+
else
Result := Left_Int rem Right_Int;
end if;
@@ -1018,7 +1117,7 @@ package body Sem_Eval is
Result := Result mod Modulus (Ltype);
end if;
- Fold_Uint (N, Result);
+ Fold_Uint (N, Result, Stat);
end;
-- Cases where at least one operand is a real. We handle the cases
@@ -1063,11 +1162,9 @@ package body Sem_Eval is
Result := Left_Real / Right_Real;
end if;
- Fold_Ureal (N, Result);
+ Fold_Ureal (N, Result, Stat);
end;
end if;
-
- Set_Is_Static_Expression (N, Stat);
end Eval_Arithmetic_Op;
----------------------------
@@ -1185,7 +1282,7 @@ package body Sem_Eval is
Set_Etype (N, Etype (Right));
end if;
- Fold_Str (N, End_String);
+ Fold_Str (N, End_String, True);
end if;
end;
end Eval_Concatenation;
@@ -1279,13 +1376,35 @@ package body Sem_Eval is
Expr : Node_Id;
begin
+ -- Check for non-static context on index values
+
Expr := First (Expressions (N));
while Present (Expr) loop
Check_Non_Static_Context (Expr);
Next (Expr);
end loop;
- -- See if this is a constant array reference
+ -- If the indexed component appears in an object renaming declaration
+ -- then we do not want to try to evaluate it, since in this case we
+ -- need the identity of the array element.
+
+ if Nkind (Parent (N)) = N_Object_Renaming_Declaration then
+ return;
+
+ -- Similarly if the indexed component appears as the prefix of an
+ -- attribute we don't want to evaluate it, because at least for
+ -- some cases of attributes we need the identify (e.g. Access, Size)
+
+ elsif Nkind (Parent (N)) = N_Attribute_Reference then
+ return;
+ end if;
+
+ -- Note: there are other cases, such as the left side of an assignment,
+ -- or an OUT parameter for a call, where the replacement results in the
+ -- illegal use of a constant, But these cases are illegal in the first
+ -- place, so the replacement, though silly, is harmless.
+
+ -- Now see if this is a constant array reference
if List_Length (Expressions (N)) = 1
and then Is_Entity_Name (Prefix (N))
@@ -1446,7 +1565,7 @@ package body Sem_Eval is
end loop;
end if;
- Fold_Uint (N, From_Bits (Left_Bits, Etype (N)));
+ Fold_Uint (N, From_Bits (Left_Bits, Etype (N)), Stat);
end;
else
@@ -1454,20 +1573,18 @@ package body Sem_Eval is
if Nkind (N) = N_Op_And then
Fold_Uint (N,
- Test (Is_True (Left_Int) and then Is_True (Right_Int)));
+ Test (Is_True (Left_Int) and then Is_True (Right_Int)), Stat);
elsif Nkind (N) = N_Op_Or then
Fold_Uint (N,
- Test (Is_True (Left_Int) or else Is_True (Right_Int)));
+ Test (Is_True (Left_Int) or else Is_True (Right_Int)), Stat);
else
pragma Assert (Nkind (N) = N_Op_Xor);
Fold_Uint (N,
- Test (Is_True (Left_Int) xor Is_True (Right_Int)));
+ Test (Is_True (Left_Int) xor Is_True (Right_Int)), Stat);
end if;
end if;
-
- Set_Is_Static_Expression (N, Stat);
end;
end Eval_Logical_Op;
@@ -1601,9 +1718,8 @@ package body Sem_Eval is
Result := not Result;
end if;
- Fold_Uint (N, Test (Result));
+ Fold_Uint (N, Test (Result), True);
Warn_On_Known_Condition (N);
-
end Eval_Membership_Op;
------------------------
@@ -1613,7 +1729,7 @@ package body Sem_Eval is
procedure Eval_Named_Integer (N : Node_Id) is
begin
Fold_Uint (N,
- Expr_Value (Expression (Declaration_Node (Entity (N)))));
+ Expr_Value (Expression (Declaration_Node (Entity (N)))), True);
end Eval_Named_Integer;
---------------------
@@ -1623,7 +1739,7 @@ package body Sem_Eval is
procedure Eval_Named_Real (N : Node_Id) is
begin
Fold_Ureal (N,
- Expr_Value_R (Expression (Declaration_Node (Entity (N)))));
+ Expr_Value_R (Expression (Declaration_Node (Entity (N)))), True);
end Eval_Named_Real;
-------------------
@@ -1667,7 +1783,9 @@ package body Sem_Eval is
if Right_Int < 0 then
Apply_Compile_Time_Constraint_Error
- (N, "integer exponent negative", CE_Range_Check_Failed);
+ (N, "integer exponent negative",
+ CE_Range_Check_Failed,
+ Warn => not Stat);
return;
else
@@ -1681,7 +1799,7 @@ package body Sem_Eval is
Result := Result mod Modulus (Etype (N));
end if;
- Fold_Uint (N, Result);
+ Fold_Uint (N, Result, Stat);
end if;
end;
@@ -1698,19 +1816,19 @@ package body Sem_Eval is
if Right_Int < 0 then
Apply_Compile_Time_Constraint_Error
- (N, "zero ** negative integer", CE_Range_Check_Failed);
+ (N, "zero ** negative integer",
+ CE_Range_Check_Failed,
+ Warn => not Stat);
return;
else
- Fold_Ureal (N, Ureal_0);
+ Fold_Ureal (N, Ureal_0, Stat);
end if;
else
- Fold_Ureal (N, Left_Real ** Right_Int);
+ Fold_Ureal (N, Left_Real ** Right_Int, Stat);
end if;
end;
end if;
-
- Set_Is_Static_Expression (N, Stat);
end;
end Eval_Op_Expon;
@@ -1748,11 +1866,11 @@ package body Sem_Eval is
-- is an arbitrary but consistent definition.
if Is_Modular_Integer_Type (Typ) then
- Fold_Uint (N, Modulus (Typ) - 1 - Rint);
+ Fold_Uint (N, Modulus (Typ) - 1 - Rint, Stat);
else
pragma Assert (Is_Boolean_Type (Typ));
- Fold_Uint (N, Test (not Is_True (Rint)));
+ Fold_Uint (N, Test (not Is_True (Rint)), Stat);
end if;
Set_Is_Static_Expression (N, Stat);
@@ -1811,8 +1929,7 @@ package body Sem_Eval is
-- Fold the result of qualification
if Is_Discrete_Type (Target_Type) then
- Fold_Uint (N, Expr_Value (Operand));
- Set_Is_Static_Expression (N, Stat);
+ Fold_Uint (N, Expr_Value (Operand), Stat);
-- Preserve Print_In_Hex indication
@@ -1821,11 +1938,10 @@ package body Sem_Eval is
end if;
elsif Is_Real_Type (Target_Type) then
- Fold_Ureal (N, Expr_Value_R (Operand));
- Set_Is_Static_Expression (N, Stat);
+ Fold_Ureal (N, Expr_Value_R (Operand), Stat);
else
- Fold_Str (N, Strval (Get_String_Val (Operand)));
+ Fold_Str (N, Strval (Get_String_Val (Operand)), Stat);
if not Stat then
Set_Is_Static_Expression (N, False);
@@ -1836,10 +1952,13 @@ package body Sem_Eval is
return;
end if;
+ -- The expression may be foldable but not static
+
+ Set_Is_Static_Expression (N, Stat);
+
if Is_Out_Of_Range (N, Etype (N)) then
Out_Of_Range (N);
end if;
-
end Eval_Qualified_Expression;
-----------------------
@@ -1903,6 +2022,10 @@ package body Sem_Eval is
-- known at compile time length, then Len is set to this
-- (non-negative length). Otherwise Len is set to minus 1.
+ -----------------------
+ -- Get_Static_Length --
+ -----------------------
+
procedure Get_Static_Length (Op : Node_Id; Len : out Uint) is
T : Entity_Id;
@@ -1942,8 +2065,7 @@ package body Sem_Eval is
and then Len_R /= Uint_Minus_1
and then Len_L /= Len_R
then
- Fold_Uint (N, Test (Nkind (N) = N_Op_Ne));
- Set_Is_Static_Expression (N, False);
+ Fold_Uint (N, Test (Nkind (N) = N_Op_Ne), False);
Warn_On_Known_Condition (N);
return;
end if;
@@ -1986,7 +2108,7 @@ package body Sem_Eval is
raise Program_Error;
end case;
- Fold_Uint (N, Test (Result));
+ Fold_Uint (N, Test (Result), Stat);
end;
-- Real type case
@@ -2011,11 +2133,10 @@ package body Sem_Eval is
raise Program_Error;
end case;
- Fold_Uint (N, Test (Result));
+ Fold_Uint (N, Test (Result), Stat);
end;
end if;
- Set_Is_Static_Expression (N, Stat);
Warn_On_Known_Condition (N);
end Eval_Relational_Op;
@@ -2114,7 +2235,7 @@ package body Sem_Eval is
if (Kind = N_And_Then and then Is_False (Left_Int))
or else (Kind = N_Or_Else and Is_True (Left_Int))
then
- Fold_Uint (N, Left_Int);
+ Fold_Uint (N, Left_Int, Rstat);
return;
end if;
@@ -2132,9 +2253,8 @@ package body Sem_Eval is
-- Otherwise the result depends on the right operand
- Fold_Uint (N, Expr_Value (Right));
+ Fold_Uint (N, Expr_Value (Right), Rstat);
return;
-
end Eval_Short_Circuit;
----------------
@@ -2244,6 +2364,10 @@ package body Sem_Eval is
-- fixed-point type that is not to be treated as an integer (i.e. the
-- flag Conversion_OK is not set on the conversion node).
+ ------------------------------
+ -- To_Be_Treated_As_Integer --
+ ------------------------------
+
function To_Be_Treated_As_Integer (T : Entity_Id) return Boolean is
begin
return
@@ -2251,6 +2375,10 @@ package body Sem_Eval is
or else (Is_Fixed_Point_Type (T) and then Conversion_OK (N));
end To_Be_Treated_As_Integer;
+ ---------------------------
+ -- To_Be_Treated_As_Real --
+ ---------------------------
+
function To_Be_Treated_As_Real (T : Entity_Id) return Boolean is
begin
return
@@ -2292,8 +2420,7 @@ package body Sem_Eval is
-- Fold conversion, case of string type. The result is not static.
if Is_String_Type (Target_Type) then
- Fold_Str (N, Strval (Get_String_Val (Operand)));
- Set_Is_Static_Expression (N, False);
+ Fold_Str (N, Strval (Get_String_Val (Operand)), False);
return;
@@ -2322,12 +2449,12 @@ package body Sem_Eval is
if Is_Fixed_Point_Type (Target_Type) then
Fold_Ureal
- (N, UR_From_Uint (Result) * Small_Value (Target_Type));
+ (N, UR_From_Uint (Result) * Small_Value (Target_Type), Stat);
-- Otherwise result is integer literal
else
- Fold_Uint (N, Result);
+ Fold_Uint (N, Result, Stat);
end if;
end;
@@ -2344,17 +2471,15 @@ package body Sem_Eval is
Result := UR_From_Uint (Expr_Value (Operand));
end if;
- Fold_Ureal (N, Result);
+ Fold_Ureal (N, Result, Stat);
end;
-- Enumeration types
else
- Fold_Uint (N, Expr_Value (Operand));
+ Fold_Uint (N, Expr_Value (Operand), Stat);
end if;
- Set_Is_Static_Expression (N, Stat);
-
if Is_Out_Of_Range (N, Etype (N)) then
Out_Of_Range (N);
end if;
@@ -2412,7 +2537,7 @@ package body Sem_Eval is
Result := abs Rint;
end if;
- Fold_Uint (N, Result);
+ Fold_Uint (N, Result, Stat);
end;
-- Fold for real case
@@ -2434,12 +2559,9 @@ package body Sem_Eval is
Result := abs Rreal;
end if;
- Fold_Ureal (N, Result);
+ Fold_Ureal (N, Result, Stat);
end;
end if;
-
- Set_Is_Static_Expression (N, Stat);
-
end Eval_Unary_Op;
-------------------------------
@@ -2691,40 +2813,79 @@ package body Sem_Eval is
end if;
end Expr_Value_S;
+ --------------------------
+ -- Flag_Non_Static_Expr --
+ --------------------------
+
+ procedure Flag_Non_Static_Expr (Msg : String; Expr : Node_Id) is
+ begin
+ if Error_Posted (Expr) and then not All_Errors_Mode then
+ return;
+ else
+ Error_Msg_F (Msg, Expr);
+ Why_Not_Static (Expr);
+ end if;
+ end Flag_Non_Static_Expr;
+
--------------
-- Fold_Str --
--------------
- procedure Fold_Str (N : Node_Id; Val : String_Id) is
+ procedure Fold_Str (N : Node_Id; Val : String_Id; Static : Boolean) is
Loc : constant Source_Ptr := Sloc (N);
Typ : constant Entity_Id := Etype (N);
begin
Rewrite (N, Make_String_Literal (Loc, Strval => Val));
- Analyze_And_Resolve (N, Typ);
+
+ -- We now have the literal with the right value, both the actual type
+ -- and the expected type of this literal are taken from the expression
+ -- that was evaluated.
+
+ Analyze (N);
+ Set_Is_Static_Expression (N, Static);
+ Set_Etype (N, Typ);
+ Resolve (N);
end Fold_Str;
---------------
-- Fold_Uint --
---------------
- procedure Fold_Uint (N : Node_Id; Val : Uint) is
+ procedure Fold_Uint (N : Node_Id; Val : Uint; Static : Boolean) is
Loc : constant Source_Ptr := Sloc (N);
- Typ : constant Entity_Id := Etype (N);
+ Typ : Entity_Id := Etype (N);
+ Ent : Entity_Id;
begin
+ -- 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
+ then
+ Ent := Entity (N);
+ else
+ Ent := Empty;
+ end if;
+
+ if Is_Private_Type (Typ) then
+ Typ := Full_View (Typ);
+ end if;
+
-- For a result of type integer, subsitute an N_Integer_Literal node
-- for the result of the compile time evaluation of the expression.
- if Is_Integer_Type (Etype (N)) then
+ if Is_Integer_Type (Typ) then
Rewrite (N, Make_Integer_Literal (Loc, Val));
+ Set_Original_Entity (N, Ent);
-- Otherwise we have an enumeration type, and we substitute either
-- an N_Identifier or N_Character_Literal to represent the enumeration
-- literal corresponding to the given value, which must always be in
-- range, because appropriate tests have already been made for this.
- else pragma Assert (Is_Enumeration_Type (Etype (N)));
+ else pragma Assert (Is_Enumeration_Type (Typ));
Rewrite (N, Get_Enum_Lit_From_Pos (Etype (N), Val, Loc));
end if;
@@ -2733,26 +2894,41 @@ package body Sem_Eval is
-- that was evaluated.
Analyze (N);
+ Set_Is_Static_Expression (N, Static);
Set_Etype (N, Typ);
- Resolve (N, Typ);
+ Resolve (N);
end Fold_Uint;
----------------
-- Fold_Ureal --
----------------
- procedure Fold_Ureal (N : Node_Id; Val : Ureal) is
+ procedure Fold_Ureal (N : Node_Id; Val : Ureal; Static : Boolean) is
Loc : constant Source_Ptr := Sloc (N);
Typ : constant Entity_Id := Etype (N);
+ Ent : Entity_Id;
begin
+ -- 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
+ then
+ Ent := Entity (N);
+ else
+ Ent := Empty;
+ end if;
+
Rewrite (N, Make_Real_Literal (Loc, Realval => Val));
- Analyze (N);
+ Set_Original_Entity (N, Ent);
-- Both the actual and expected type comes from the original expression
+ Analyze (N);
+ Set_Is_Static_Expression (N, Static);
Set_Etype (N, Typ);
- Resolve (N, Typ);
+ Resolve (N);
end Fold_Ureal;
---------------
@@ -2794,6 +2970,15 @@ package body Sem_Eval is
end if;
end Get_String_Val;
+ ----------------
+ -- Initialize --
+ ----------------
+
+ procedure Initialize is
+ begin
+ CV_Cache := (others => (Node_High_Bound, Uint_0));
+ end Initialize;
+
--------------------
-- In_Subrange_Of --
--------------------
@@ -3112,7 +3297,7 @@ package body Sem_Eval is
elsif Is_Generic_Type (Typ) then
return False;
- -- Never out of range unless we have a compile time known value.
+ -- Never out of range unless we have a compile time known value
elsif not Compile_Time_Known_Value (N) then
return False;
@@ -3291,9 +3476,9 @@ package body Sem_Eval is
if Is_Static_Expression (N)
and then not In_Instance
+ and then not In_Inlined_Body
and then Ada_95
then
-
if Nkind (Parent (N)) = N_Defining_Identifier
and then Is_Array_Type (Parent (N))
and then Present (Packed_Array_Type (Parent (N)))
@@ -3313,10 +3498,8 @@ package body Sem_Eval is
-- in an instance, or when we have a non-static expression case.
else
- Warn_On_Instance := True;
Apply_Compile_Time_Constraint_Error
(N, "value not in range of}?", CE_Range_Check_Failed);
- Warn_On_Instance := False;
end if;
end Out_Of_Range;
@@ -3409,7 +3592,7 @@ package body Sem_Eval is
-- we???) but we do at least check that both types are
-- real, or both types are not real.
- elsif (Is_Real_Type (T1) /= Is_Real_Type (T2)) then
+ elsif Is_Real_Type (T1) /= Is_Real_Type (T2) then
return False;
-- Here we check the bounds
@@ -3832,4 +4015,256 @@ package body Sem_Eval is
end loop;
end To_Bits;
+ --------------------
+ -- Why_Not_Static --
+ --------------------
+
+ procedure Why_Not_Static (Expr : Node_Id) is
+ N : constant Node_Id := Original_Node (Expr);
+ Typ : Entity_Id;
+ 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.
+
+ -------------------------
+ -- Why_Not_Static_List --
+ -------------------------
+
+ procedure Why_Not_Static_List (L : List_Id) is
+ N : Node_Id;
+
+ begin
+ if Is_Non_Empty_List (L) then
+ N := First (L);
+ while Present (N) loop
+ Why_Not_Static (N);
+ Next (N);
+ end loop;
+ end if;
+ end Why_Not_Static_List;
+
+ -- 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 Debug_Flag_2 then
+ return;
+ end if;
+
+ -- Ignore call on error or empty node
+
+ if No (Expr) or else Nkind (Expr) = N_Error then
+ return;
+ end if;
+
+ -- Preprocessing for sub expressions
+
+ if Nkind (Expr) in N_Subexpr then
+
+ -- Nothing to do if expression is static
+
+ if Is_OK_Static_Expression (Expr) then
+ return;
+ end if;
+
+ -- Test for constraint error raised
+
+ if Raises_Constraint_Error (Expr) then
+ Error_Msg_N
+ ("expression raises exception, cannot be static " &
+ "('R'M 4.9(34))!", N);
+ return;
+ end if;
+
+ -- If no type, then something is pretty wrong, so ignore
+
+ Typ := Etype (Expr);
+
+ if No (Typ) then
+ return;
+ end if;
+
+ -- Type must be scalar or string type
+
+ if not Is_Scalar_Type (Typ)
+ and then not Is_String_Type (Typ)
+ then
+ Error_Msg_N
+ ("static expression must have scalar or string type " &
+ "('R'M 4.9(2))!", N);
+ return;
+ end if;
+ end if;
+
+ -- If we got through those checks, test particular node kind
+
+ case Nkind (N) is
+ when N_Expanded_Name | N_Identifier | N_Operator_Symbol =>
+ E := Entity (N);
+
+ if Is_Named_Number (E) then
+ null;
+
+ elsif Ekind (E) = E_Constant then
+ if not Is_Static_Expression (Constant_Value (E)) then
+ Error_Msg_NE
+ ("& is not a static constant ('R'M 4.9(5))!", N, E);
+ end if;
+
+ else
+ Error_Msg_NE
+ ("& is not static constant or named number " &
+ "('R'M 4.9(5))!", N, E);
+ end if;
+
+ when N_Binary_Op | N_And_Then | N_Or_Else | N_In | N_Not_In =>
+ if Nkind (N) in N_Op_Shift then
+ Error_Msg_N
+ ("shift functions are never static ('R'M 4.9(6,18))!", N);
+
+ else
+ Why_Not_Static (Left_Opnd (N));
+ Why_Not_Static (Right_Opnd (N));
+ end if;
+
+ when N_Unary_Op =>
+ Why_Not_Static (Right_Opnd (N));
+
+ when N_Attribute_Reference =>
+ Why_Not_Static_List (Expressions (N));
+
+ E := Etype (Prefix (N));
+
+ if E = Standard_Void_Type then
+ return;
+ end if;
+
+ -- Special case non-scalar'Size since this is a common error
+
+ if Attribute_Name (N) = Name_Size then
+ Error_Msg_N
+ ("size attribute is only static for scalar type " &
+ "('R'M 4.9(7,8))", N);
+
+ -- Flag array cases
+
+ elsif Is_Array_Type (E) then
+ if Attribute_Name (N) /= Name_First
+ and then
+ Attribute_Name (N) /= Name_Last
+ and then
+ Attribute_Name (N) /= Name_Length
+ then
+ Error_Msg_N
+ ("static array attribute must be Length, First, or Last " &
+ "('R'M 4.9(8))!", N);
+
+ -- Since we know the expression is not-static (we already
+ -- tested for this, must mean array is not static).
+
+ else
+ Error_Msg_N
+ ("prefix is non-static array ('R'M 4.9(8))!", Prefix (N));
+ end if;
+
+ return;
+
+ -- Special case generic types, since again this is a common
+ -- source of confusion.
+
+ elsif Is_Generic_Actual_Type (E)
+ or else
+ Is_Generic_Type (E)
+ then
+ Error_Msg_N
+ ("attribute of generic type is never static " &
+ "('R'M 4.9(7,8))!", N);
+
+ elsif Is_Static_Subtype (E) then
+ null;
+
+ elsif Is_Scalar_Type (E) then
+ Error_Msg_N
+ ("prefix type for attribute is not static scalar subtype " &
+ "('R'M 4.9(7))!", N);
+
+ else
+ Error_Msg_N
+ ("static attribute must apply to array/scalar type " &
+ "('R'M 4.9(7,8))!", N);
+ end if;
+
+ when N_String_Literal =>
+ Error_Msg_N
+ ("subtype of string literal is non-static ('R'M 4.9(4))!", N);
+
+ when N_Explicit_Dereference =>
+ Error_Msg_N
+ ("explicit dereference is never static ('R'M 4.9)!", N);
+
+ when N_Function_Call =>
+ Why_Not_Static_List (Parameter_Associations (N));
+ Error_Msg_N ("non-static function call ('R'M 4.9(6,18))!", N);
+
+ when N_Parameter_Association =>
+ Why_Not_Static (Explicit_Actual_Parameter (N));
+
+ when N_Indexed_Component =>
+ Error_Msg_N
+ ("indexed component is never static ('R'M 4.9)!", N);
+
+ when N_Procedure_Call_Statement =>
+ Error_Msg_N
+ ("procedure call is never static ('R'M 4.9)!", N);
+
+ when N_Qualified_Expression =>
+ Why_Not_Static (Expression (N));
+
+ when N_Aggregate | N_Extension_Aggregate =>
+ Error_Msg_N
+ ("an aggregate is never static ('R'M 4.9)!", N);
+
+ when N_Range =>
+ Why_Not_Static (Low_Bound (N));
+ Why_Not_Static (High_Bound (N));
+
+ when N_Range_Constraint =>
+ Why_Not_Static (Range_Expression (N));
+
+ when N_Subtype_Indication =>
+ Why_Not_Static (Constraint (N));
+
+ when N_Selected_Component =>
+ Error_Msg_N
+ ("selected component is never static ('R'M 4.9)!", N);
+
+ when N_Slice =>
+ Error_Msg_N
+ ("slice is never static ('R'M 4.9)!", N);
+
+ when N_Type_Conversion =>
+ Why_Not_Static (Expression (N));
+
+ if not Is_Scalar_Type (Etype (Prefix (N)))
+ or else not Is_Static_Subtype (Etype (Prefix (N)))
+ then
+ Error_Msg_N
+ ("static conversion requires static scalar subtype result " &
+ "('R'M 4.9(9))!", N);
+ end if;
+
+ when N_Unchecked_Type_Conversion =>
+ Error_Msg_N
+ ("unchecked type conversion is never static ('R'M 4.9)!", N);
+
+ when others =>
+ null;
+
+ end case;
+ end Why_Not_Static;
+
end Sem_Eval;