This patch fixes a spurious error on a case statement whose expression is a
type conversion of a variable whose initial value is known, and whose type
has a static predicate.
Executing:
gnatmake -q static_predicate_example
static_predicate_example
gnatmake -q -f -gnata static_predicate_example
static_predicate_example
must yield:
woof
woof
woof
woof
---
with Ada.Text_Io;
procedure Static_Predicate_Example is
type Animal_Type is (Bear, Cat, Dog, Horse, Wolf);
subtype Pet_Type is Animal_Type with Static_Predicate =>
(case Pet_Type is
when Cat | Dog | Horse => True,
when Bear | Wolf => False);
My_Animal : Animal_Type := Dog;
My_Animal_Converted : Pet_Type := Pet_Type (My_Animal);
begin
if My_Animal in Pet_Type then
case Pet_Type (My_Animal) is
when Cat => Ada.Text_Io.Put_Line ("meow");
when Dog => Ada.Text_Io.Put_Line ("woof");
when Horse => Ada.Text_Io.Put_Line ("eeehehe");
end case;
end if;
case My_Animal_Converted is
when Cat => Ada.Text_Io.Put_Line ("meow");
when Dog => Ada.Text_Io.Put_Line ("woof");
when Horse => Ada.Text_Io.Put_Line ("eeehehe");
end case;
end Static_Predicate_Example;
Tested on x86_64-pc-linux-gnu, committed on trunk
2017-01-06 Ed Schonberg <[email protected]>
* sem_eval.adb (Check_Expression_Against_Static_Predicate):
If expression is compile-time known and obeys a static predicate
it must be labelled as static, to prevent spurious warnings and
run-time errors, e.g. in case statements. This is relevant when
the expression is the result of constant-folding a type conversion
whose expression is a variable with a known static value.
Index: sem_eval.adb
===================================================================
--- sem_eval.adb (revision 244124)
+++ sem_eval.adb (working copy)
@@ -347,7 +347,11 @@
-- Here we have a static predicate (note that it could have arisen from
-- an explicitly specified Dynamic_Predicate whose expression met the
- -- rules for being predicate-static).
+ -- rules for being predicate-static). If the expression is known at
+ -- compile time and obeys the predicate, then it is static and must be
+ -- labeled as such, which matters e.g. for case statements. The original
+ -- expression may be a type conversion of a variable with a known value,
+ -- which might otherwise not be marked static.
-- Case of real static predicate
@@ -356,6 +360,7 @@
(Val => Make_Real_Literal (Sloc (Expr), Expr_Value_R (Expr)),
Typ => Typ)
then
+ Set_Is_Static_Expression (Expr);
return;
end if;
@@ -365,6 +370,7 @@
if Real_Or_String_Static_Predicate_Matches
(Val => Expr_Value_S (Expr), Typ => Typ)
then
+ Set_Is_Static_Expression (Expr);
return;
end if;
@@ -376,6 +382,7 @@
-- If static predicate matches, nothing to do
if Choices_Match (Expr, Static_Discrete_Predicate (Typ)) = Match then
+ Set_Is_Static_Expression (Expr);
return;
end if;
end if;