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 <schonb...@adacore.com> * 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;