aboutsummaryrefslogtreecommitdiff
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.adb695
1 files changed, 387 insertions, 308 deletions
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
index 5a8c27b..8556149 100644
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2016, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2017, 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- --
@@ -3144,274 +3144,364 @@ package body Sem_Eval is
-- equality test A = "ABC", and the former is definitely static.
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;
+ Left : constant Node_Id := Left_Opnd (N);
+ Right : constant Node_Id := Right_Opnd (N);
- begin
- -- One special case to deal with first. If we can tell that the result
- -- will be false because the lengths of one or more index subtypes are
- -- compile time known and different, then we can replace the entire
- -- result by False. We only do this for one dimensional arrays, because
- -- the case of multi-dimensional arrays is rare and too much trouble. If
- -- one of the operands is an illegal aggregate, its type might still be
- -- an arbitrary composite type, so nothing to do.
+ procedure Decompose_Expr
+ (Expr : Node_Id;
+ Ent : out Entity_Id;
+ Kind : out Character;
+ Cons : out Uint;
+ Orig : Boolean := True);
+ -- Given expression Expr, see if it is of the form X [+/- K]. If so, Ent
+ -- is set to the entity in X, Kind is 'F','L','E' for 'First or 'Last or
+ -- simple entity, and Cons is the value of K. If the expression is not
+ -- of the required form, Ent is set to Empty.
+ --
+ -- Orig indicates whether Expr is the original expression to consider,
+ -- or if we are handling a sub-expression (e.g. recursive call to
+ -- Decompose_Expr).
+
+ procedure Fold_General_Op (Is_Static : Boolean);
+ -- Attempt to fold arbitrary relational operator N. Flag Is_Static must
+ -- be set when the operator denotes a static expression.
+
+ procedure Fold_Static_Real_Op;
+ -- Attempt to fold static real type relational operator N
+
+ function Static_Length (Expr : Node_Id) return Uint;
+ -- If Expr is an expression for a constrained array whose length is
+ -- known at compile time, return the non-negative length, otherwise
+ -- return -1.
+
+ --------------------
+ -- Decompose_Expr --
+ --------------------
+
+ procedure Decompose_Expr
+ (Expr : Node_Id;
+ Ent : out Entity_Id;
+ Kind : out Character;
+ Cons : out Uint;
+ Orig : Boolean := True)
+ is
+ Exp : Node_Id;
- if Is_Array_Type (Typ)
- and then Typ /= Any_Composite
- and then Number_Dimensions (Typ) = 1
- and then (Nkind (N) = N_Op_Eq or else Nkind (N) = N_Op_Ne)
- then
- if Raises_Constraint_Error (Left)
- or else
- Raises_Constraint_Error (Right)
+ begin
+ -- Assume that the expression does not meet the expected form
+
+ Cons := No_Uint;
+ Ent := Empty;
+ Kind := '?';
+
+ if Nkind (Expr) = N_Op_Add
+ and then Compile_Time_Known_Value (Right_Opnd (Expr))
then
- return;
+ 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);
+ Cons := -Expr_Value (Right_Opnd (Expr));
+
+ -- If the bound is a constant created to remove side effects, recover
+ -- the 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, Orig => False);
+
+ -- 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));
+ else
+ return;
+ end if;
+
+ else
+ -- Only consider the case of X + 0 for a full expression, and
+ -- not when recursing, otherwise we may end up with evaluating
+ -- expressions not known at compile time to 0.
+
+ if Orig then
+ Exp := Expr;
+ Cons := Uint_0;
+ else
+ return;
+ end if;
end if;
- -- OK, we have the case where we may be able to do this fold
+ -- At this stage Exp is set to the potential X
- Length_Mismatch : declare
- procedure Get_Static_Length (Op : Node_Id; Len : out Uint);
- -- If Op is an expression for a constrained array with a known at
- -- compile time length, then Len is set to this (non-negative
- -- length). Otherwise Len is set to minus 1.
+ 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
+ return;
+ end if;
- -----------------------
- -- Get_Static_Length --
- -----------------------
+ Exp := Prefix (Exp);
- procedure Get_Static_Length (Op : Node_Id; Len : out Uint) is
- T : Entity_Id;
+ else
+ Kind := 'E';
+ end if;
- begin
- -- First easy case string literal
+ if Is_Entity_Name (Exp) and then Present (Entity (Exp)) then
+ Ent := Entity (Exp);
+ end if;
+ end Decompose_Expr;
+
+ ---------------------
+ -- Fold_General_Op --
+ ---------------------
+
+ procedure Fold_General_Op (Is_Static : Boolean) is
+ CR : constant Compare_Result :=
+ Compile_Time_Compare (Left, Right, Assume_Valid => False);
- if Nkind (Op) = N_String_Literal then
- Len := UI_From_Int (String_Length (Strval (Op)));
+ Result : Boolean;
+
+ begin
+ if CR = Unknown then
+ return;
+ end if;
+
+ case Nkind (N) is
+ when N_Op_Eq =>
+ if CR = EQ then
+ Result := True;
+ elsif CR = NE or else CR = GT or else CR = LT then
+ Result := False;
+ else
return;
end if;
- -- Second easy case, not constrained subtype, so no length
-
- if not Is_Constrained (Etype (Op)) then
- Len := Uint_Minus_1;
+ when N_Op_Ge =>
+ if CR = GT or else CR = EQ or else CR = GE then
+ Result := True;
+ elsif CR = LT then
+ Result := False;
+ else
return;
end if;
- -- General case
+ when N_Op_Gt =>
+ if CR = GT then
+ Result := True;
+ elsif CR = EQ or else CR = LT or else CR = LE then
+ Result := False;
+ else
+ return;
+ end if;
- T := Etype (First_Index (Etype (Op)));
+ when N_Op_Le =>
+ if CR = LT or else CR = EQ or else CR = LE then
+ Result := True;
+ elsif CR = GT then
+ Result := False;
+ else
+ return;
+ end if;
- -- The simple case, both bounds are known at compile time
+ when N_Op_Lt =>
+ if CR = LT then
+ Result := True;
+ elsif CR = EQ or else CR = GT or else CR = GE then
+ Result := False;
+ else
+ return;
+ end if;
- if Is_Discrete_Type (T)
- and then Compile_Time_Known_Value (Type_Low_Bound (T))
- and then Compile_Time_Known_Value (Type_High_Bound (T))
- then
- Len := UI_Max (Uint_0,
- Expr_Value (Type_High_Bound (T)) -
- Expr_Value (Type_Low_Bound (T)) + 1);
+ when N_Op_Ne =>
+ if CR = NE or else CR = GT or else CR = LT then
+ Result := True;
+ elsif CR = EQ then
+ Result := False;
+ else
return;
end if;
- -- A more complex case, where the bounds are of the form
- -- X [+/- K1] .. X [+/- K2]), where X is an expression that is
- -- either A'First or A'Last (with A an entity name), or X is an
- -- 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).
-
- Extract_Length : declare
- procedure Decompose_Expr
- (Expr : Node_Id;
- Ent : out Entity_Id;
- Kind : out Character;
- Cons : out Uint;
- Orig : Boolean := True);
- -- Given an expression see if it is of the form given above,
- -- X [+/- K]. If so Ent is set to the entity in X, Kind is
- -- 'F','L','E' for 'First/'Last/simple entity, and Cons is
- -- the value of K. If the expression is not of the required
- -- form, Ent is set to Empty.
- --
- -- Orig indicates whether Expr is the original expression
- -- to consider, or if we are handling a sub-expression
- -- (e.g. recursive call to Decompose_Expr).
-
- --------------------
- -- Decompose_Expr --
- --------------------
-
- procedure Decompose_Expr
- (Expr : Node_Id;
- Ent : out Entity_Id;
- Kind : out Character;
- Cons : out Uint;
- Orig : Boolean := True)
- is
- Exp : Node_Id;
+ when others =>
+ raise Program_Error;
+ end case;
- begin
- Ent := Empty;
+ -- Determine the potential outcome of the relation assuming the
+ -- operands are valid and emit a warning when the relation yields
+ -- True or False only in the presence of invalid values.
- -- Ignored values:
+ Warn_On_Constant_Valid_Condition (N);
- Kind := '?';
- Cons := No_Uint;
+ Fold_Uint (N, Test (Result), Is_Static);
+ end Fold_General_Op;
- if Nkind (Expr) = N_Op_Add
- and then Compile_Time_Known_Value (Right_Opnd (Expr))
- then
- Exp := Left_Opnd (Expr);
- Cons := Expr_Value (Right_Opnd (Expr));
+ -------------------------
+ -- Fold_Static_Real_Op --
+ -------------------------
- elsif Nkind (Expr) = N_Op_Subtract
- and then Compile_Time_Known_Value (Right_Opnd (Expr))
- then
- Exp := Left_Opnd (Expr);
- Cons := -Expr_Value (Right_Opnd (Expr));
+ procedure Fold_Static_Real_Op is
+ Left_Real : constant Ureal := Expr_Value_R (Left);
+ Right_Real : constant Ureal := Expr_Value_R (Right);
+ Result : Boolean;
- -- If the bound is a constant created to remove side
- -- effects, recover original expression to see if it has
- -- one of the recognizable forms.
+ begin
+ case Nkind (N) is
+ when N_Op_Eq => Result := (Left_Real = Right_Real);
+ when N_Op_Ge => Result := (Left_Real >= Right_Real);
+ when N_Op_Gt => Result := (Left_Real > Right_Real);
+ when N_Op_Le => Result := (Left_Real <= Right_Real);
+ when N_Op_Lt => Result := (Left_Real < Right_Real);
+ when N_Op_Ne => Result := (Left_Real /= Right_Real);
+ when others => raise Program_Error;
+ end case;
+
+ Fold_Uint (N, Test (Result), True);
+ end Fold_Static_Real_Op;
- 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, Orig => False);
+ -------------------
+ -- Static_Length --
+ -------------------
- -- If original expression includes an entity, create a
- -- reference to it for use below.
+ function Static_Length (Expr : Node_Id) return Uint is
+ Cons1 : Uint;
+ Cons2 : Uint;
+ Ent1 : Entity_Id;
+ Ent2 : Entity_Id;
+ Kind1 : Character;
+ Kind2 : Character;
+ Typ : Entity_Id;
- if Present (Ent) then
- Exp := New_Occurrence_Of (Ent, Sloc (Ent));
- else
- return;
- end if;
+ begin
+ -- First easy case string literal
- else
- -- Only consider the case of X + 0 for a full
- -- expression, and not when recursing, otherwise we
- -- may end up with evaluating expressions not known
- -- at compile time to 0.
-
- if Orig then
- Exp := Expr;
- Cons := Uint_0;
- else
- return;
- end if;
- end if;
+ if Nkind (Expr) = N_String_Literal then
+ return UI_From_Int (String_Length (Strval (Expr)));
- -- At this stage Exp is set to the potential X
+ -- Second easy case, not constrained subtype, so no length
- 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
- return;
- end if;
+ elsif not Is_Constrained (Etype (Expr)) then
+ return Uint_Minus_1;
+ end if;
- Exp := Prefix (Exp);
+ -- General case
- else
- Kind := 'E';
- end if;
+ Typ := Etype (First_Index (Etype (Expr)));
- if Is_Entity_Name (Exp)
- and then Present (Entity (Exp))
- then
- Ent := Entity (Exp);
- end if;
- end Decompose_Expr;
+ -- The simple case, both bounds are known at compile time
- -- Local Variables
+ if Is_Discrete_Type (Typ)
+ and then Compile_Time_Known_Value (Type_Low_Bound (Typ))
+ and then Compile_Time_Known_Value (Type_High_Bound (Typ))
+ then
+ return
+ UI_Max (Uint_0, Expr_Value (Type_High_Bound (Typ)) -
+ Expr_Value (Type_Low_Bound (Typ)) + 1);
+ end if;
- Ent1, Ent2 : Entity_Id;
- Kind1, Kind2 : Character;
- Cons1, Cons2 : Uint;
+ -- A more complex case, where the bounds are of the form X [+/- K1]
+ -- .. X [+/- K2]), where X is an expression that is either A'First or
+ -- A'Last (with A an entity name), or X is an 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).
+
+ Decompose_Expr
+ (Original_Node (Type_Low_Bound (Typ)), Ent1, Kind1, Cons1);
+ Decompose_Expr
+ (Original_Node (Type_High_Bound (Typ)), Ent2, Kind2, Cons2);
+
+ if Present (Ent1) and then Ent1 = Ent2 and then Kind1 = Kind2 then
+ return Cons2 - Cons1 + 1;
+ else
+ return Uint_Minus_1;
+ end if;
+ end Static_Length;
- -- Start of processing for Extract_Length
+ -- Local variables
- begin
- Decompose_Expr
- (Original_Node (Type_Low_Bound (T)), Ent1, Kind1, Cons1);
- Decompose_Expr
- (Original_Node (Type_High_Bound (T)), Ent2, Kind2, Cons2);
-
- if Present (Ent1)
- and then Ent1 = Ent2
- and then Kind1 = Kind2
- then
- Len := Cons2 - Cons1 + 1;
- else
- Len := Uint_Minus_1;
- end if;
- end Extract_Length;
- end Get_Static_Length;
+ Left_Typ : constant Entity_Id := Etype (Left);
+ Right_Typ : constant Entity_Id := Etype (Right);
+ Fold : Boolean;
+ Left_Len : Uint;
+ Op_Typ : Entity_Id := Empty;
+ Right_Len : Uint;
+
+ Is_Static_Expression : Boolean;
- -- Local Variables
+ -- Start of processing for Eval_Relational_Op
+
+ begin
+ -- One special case to deal with first. If we can tell that the result
+ -- will be false because the lengths of one or more index subtypes are
+ -- compile time known and different, then we can replace the entire
+ -- result by False. We only do this for one dimensional arrays, because
+ -- the case of multi-dimensional arrays is rare and too much trouble. If
+ -- one of the operands is an illegal aggregate, its type might still be
+ -- an arbitrary composite type, so nothing to do.
- Len_L : Uint;
- Len_R : Uint;
+ if Is_Array_Type (Left_Typ)
+ and then Left_Typ /= Any_Composite
+ and then Number_Dimensions (Left_Typ) = 1
+ and then Nkind_In (N, N_Op_Eq, N_Op_Ne)
+ then
+ if Raises_Constraint_Error (Left)
+ or else
+ Raises_Constraint_Error (Right)
+ then
+ return;
- -- Start of processing for Length_Mismatch
+ -- OK, we have the case where we may be able to do this fold
- begin
- Get_Static_Length (Left, Len_L);
- Get_Static_Length (Right, Len_R);
+ else
+ Left_Len := Static_Length (Left);
+ Right_Len := Static_Length (Right);
- if Len_L /= Uint_Minus_1
- and then Len_R /= Uint_Minus_1
- and then Len_L /= Len_R
+ if Left_Len /= Uint_Minus_1
+ and then Right_Len /= Uint_Minus_1
+ and then Left_Len /= Right_Len
then
Fold_Uint (N, Test (Nkind (N) = N_Op_Ne), False);
Warn_On_Known_Condition (N);
return;
end if;
- end Length_Mismatch;
- end if;
-
- declare
- Is_Static_Expression : Boolean;
+ end if;
- Is_Foldable : Boolean;
- pragma Unreferenced (Is_Foldable);
+ -- General case
- begin
- -- Initialize the value of Is_Static_Expression. The value of
- -- Is_Foldable returned by Test_Expression_Is_Foldable is not needed
- -- since, even when some operand is a variable, we can still perform
- -- the static evaluation of the expression in some cases (for
- -- example, for a variable of a subtype of Integer we statically
- -- know that any value stored in such variable is smaller than
- -- Integer'Last).
+ else
+ -- Initialize the value of Is_Static_Expression. The value of Fold
+ -- returned by Test_Expression_Is_Foldable is not needed since, even
+ -- when some operand is a variable, we can still perform the static
+ -- evaluation of the expression in some cases (for example, for a
+ -- variable of a subtype of Integer we statically know that any value
+ -- stored in such variable is smaller than Integer'Last).
Test_Expression_Is_Foldable
- (N, Left, Right, Is_Static_Expression, Is_Foldable);
+ (N, Left, Right, Is_Static_Expression, Fold);
- -- Only comparisons of scalars can give static results. In
- -- particular, comparisons of strings never yield a static
- -- result, even if both operands are static strings, except that
- -- as noted above, we allow equality/inequality for strings.
+ -- Only comparisons of scalars can give static results. A comparison
+ -- of strings never yields a static result, even if both operands are
+ -- static strings, except that as noted above, we allow equality and
+ -- inequality for strings.
- if Is_String_Type (Typ)
+ if Is_String_Type (Left_Typ)
and then not Comes_From_Source (N)
and then Nkind_In (N, N_Op_Eq, N_Op_Ne)
then
null;
- elsif not Is_Scalar_Type (Typ) then
+ elsif not Is_Scalar_Type (Left_Typ) then
Is_Static_Expression := False;
Set_Is_Static_Expression (N, False);
end if;
@@ -3420,117 +3510,27 @@ package body Sem_Eval is
-- an explicit scope, determine appropriate specific numeric type,
-- and diagnose possible ambiguity.
- if Is_Universal_Numeric_Type (Etype (Left))
+ if Is_Universal_Numeric_Type (Left_Typ)
and then
- Is_Universal_Numeric_Type (Etype (Right))
+ Is_Universal_Numeric_Type (Right_Typ)
then
- Otype := Find_Universal_Operator_Type (N);
+ Op_Typ := Find_Universal_Operator_Type (N);
end if;
- -- For static real type expressions, do not use Compile_Time_Compare
- -- since it worries about run-time results which are not exact.
-
- if Is_Static_Expression and then Is_Real_Type (Typ) then
- declare
- Left_Real : constant Ureal := Expr_Value_R (Left);
- Right_Real : constant Ureal := Expr_Value_R (Right);
-
- begin
- case Nkind (N) is
- when N_Op_Eq => Result := (Left_Real = Right_Real);
- when N_Op_Ne => Result := (Left_Real /= Right_Real);
- when N_Op_Lt => Result := (Left_Real < Right_Real);
- when N_Op_Le => Result := (Left_Real <= Right_Real);
- when N_Op_Gt => Result := (Left_Real > Right_Real);
- when N_Op_Ge => Result := (Left_Real >= Right_Real);
- when others => raise Program_Error;
- end case;
-
- Fold_Uint (N, Test (Result), True);
- end;
-
- -- For all other cases, we use Compile_Time_Compare to do the compare
+ -- Attempt to fold the relational operator
+ if Is_Static_Expression and then Is_Real_Type (Left_Typ) then
+ Fold_Static_Real_Op;
else
- declare
- CR : constant Compare_Result :=
- Compile_Time_Compare
- (Left, Right, Assume_Valid => False);
-
- begin
- if CR = Unknown then
- return;
- end if;
-
- case Nkind (N) is
- when N_Op_Eq =>
- if CR = EQ then
- Result := True;
- elsif CR = NE or else CR = GT or else CR = LT then
- Result := False;
- else
- return;
- end if;
-
- when N_Op_Ne =>
- if CR = NE or else CR = GT or else CR = LT then
- Result := True;
- elsif CR = EQ then
- Result := False;
- else
- return;
- end if;
-
- when N_Op_Lt =>
- if CR = LT then
- Result := True;
- elsif CR = EQ or else CR = GT or else CR = GE then
- Result := False;
- else
- return;
- end if;
-
- when N_Op_Le =>
- if CR = LT or else CR = EQ or else CR = LE then
- Result := True;
- elsif CR = GT then
- Result := False;
- else
- return;
- end if;
-
- when N_Op_Gt =>
- if CR = GT then
- Result := True;
- elsif CR = EQ or else CR = LT or else CR = LE then
- Result := False;
- else
- return;
- end if;
-
- when N_Op_Ge =>
- if CR = GT or else CR = EQ or else CR = GE then
- Result := True;
- elsif CR = LT then
- Result := False;
- else
- return;
- end if;
-
- when others =>
- raise Program_Error;
- end case;
- end;
-
- Fold_Uint (N, Test (Result), Is_Static_Expression);
+ Fold_General_Op (Is_Static_Expression);
end if;
- end;
+ end if;
-- For the case of a folded relational operator on a specific numeric
- -- type, freeze operand type now.
+ -- type, freeze the operand type now.
- if Present (Otype) then
- Freeze_Before (N, Otype);
+ if Present (Op_Typ) then
+ Freeze_Before (N, Op_Typ);
end if;
Warn_On_Known_Condition (N);
@@ -6053,6 +6053,85 @@ package body Sem_Eval is
end if;
end Test;
+ ---------------------
+ -- Test_Comparison --
+ ---------------------
+
+ procedure Test_Comparison
+ (Op : Node_Id;
+ Assume_Valid : Boolean;
+ True_Result : out Boolean;
+ False_Result : out Boolean)
+ is
+ Left : constant Node_Id := Left_Opnd (Op);
+ Left_Typ : constant Entity_Id := Etype (Left);
+ Orig_Op : constant Node_Id := Original_Node (Op);
+
+ procedure Replacement_Warning (Msg : String);
+ -- Emit a warning on a comparison which can be replaced by '='
+
+ -------------------------
+ -- Replacement_Warning --
+ -------------------------
+
+ procedure Replacement_Warning (Msg : String) is
+ begin
+ if Constant_Condition_Warnings
+ and then Comes_From_Source (Orig_Op)
+ and then Is_Integer_Type (Left_Typ)
+ and then not Error_Posted (Op)
+ and then not Has_Warnings_Off (Left_Typ)
+ and then not In_Instance
+ then
+ Error_Msg_N (Msg, Op);
+ end if;
+ end Replacement_Warning;
+
+ -- Local variables
+
+ Res : constant Compare_Result :=
+ Compile_Time_Compare (Left, Right_Opnd (Op), Assume_Valid);
+
+ -- Start of processing for Test_Comparison
+
+ begin
+ case N_Op_Compare (Nkind (Op)) is
+ when N_Op_Eq =>
+ True_Result := Res = EQ;
+ False_Result := Res = LT or else Res = GT or else Res = NE;
+
+ when N_Op_Ge =>
+ True_Result := Res in Compare_GE;
+ False_Result := Res = LT;
+
+ if Res = LE and then Nkind (Orig_Op) = N_Op_Ge then
+ Replacement_Warning
+ ("can never be greater than, could replace by ""'=""?c?");
+ end if;
+
+ when N_Op_Gt =>
+ True_Result := Res = GT;
+ False_Result := Res in Compare_LE;
+
+ when N_Op_Le =>
+ True_Result := Res in Compare_LE;
+ False_Result := Res = GT;
+
+ if Res = GE and then Nkind (Orig_Op) = N_Op_Le then
+ Replacement_Warning
+ ("can never be less than, could replace by ""'=""?c?");
+ end if;
+
+ when N_Op_Lt =>
+ True_Result := Res = LT;
+ False_Result := Res in Compare_GE;
+
+ when N_Op_Ne =>
+ True_Result := Res = NE or else Res = GT or else Res = LT;
+ False_Result := Res = EQ;
+ end case;
+ end Test_Comparison;
+
---------------------------------
-- Test_Expression_Is_Foldable --
---------------------------------