Folding of Enum_Rep attribute was partly done in evaluation (for
expressions like "Typ'Enum_Rep (Enum_Literal)") and partly in expansion
(for expressions like "Enum_Literal'Enum_Rep". Moreover, some of the
code in evaluation was dead and some of the code in expansion was
violating internal assertions (when the Enum_Rep attribute was applied
to expression like "T'Last (1)").
This was confusing and required the code for expansion to be duplicated
in backends that define custom expansion (e.g. for GNATprove).
This patch activates dead folding in evaluation and deconstructs buggy
folding in expansion (which was duplicated between GNAT and GNATprove).
Tested on x86_64-pc-linux-gnu, committed on trunk
2020-06-10 Piotr Trojanek <troja...@adacore.com>
gcc/ada/
* exp_attr.adb (Expand_N_Attribute_Reference): Remove folding
for Enum_Rep attribute.
* exp_spark.adb (Expand_SPARK_N_Attribute_Reference): Remove
duplicated code for folding Enum_Rep attribute.
* sem_attr.adb (Eval_Attribute): Relax condition for folding
Enum_Rep attribute; previously dead code is now executed when
the attribute prefix is an enumeration literal; refine type in
processing of Enum_Val.
--- gcc/ada/exp_attr.adb
+++ gcc/ada/exp_attr.adb
@@ -3159,17 +3159,8 @@ package body Exp_Attr is
Expr := Pref;
end if;
- -- If the expression is an enumeration literal, it is replaced by the
- -- literal value.
-
- if Nkind (Expr) in N_Has_Entity
- and then Ekind (Entity (Expr)) = E_Enumeration_Literal
- then
- Rewrite (N,
- Make_Integer_Literal (Loc, Enumeration_Rep (Entity (Expr))));
-
- -- If not constant-folded above, Enum_Type'Enum_Rep (X) or
- -- X'Enum_Rep expands to
+ -- If not constant-folded, Enum_Type'Enum_Rep (X) or X'Enum_Rep
+ -- expands to
-- target-type (X)
@@ -3185,7 +3176,7 @@ package body Exp_Attr is
-- first convert to a small signed integer type in order not to lose
-- the size information.
- elsif Is_Enumeration_Type (Ptyp) then
+ if Is_Enumeration_Type (Ptyp) then
Psiz := RM_Size (Base_Type (Ptyp));
if Psiz < 8 then
--- gcc/ada/exp_spark.adb
+++ gcc/ada/exp_spark.adb
@@ -199,29 +199,6 @@ package body Exp_SPARK is
Parameter_Associations => New_List (Expr)));
Analyze_And_Resolve (N, Typ);
- -- Whenever possible, replace a prefix which is an enumeration literal
- -- by the corresponding literal value, just like it happens in the GNAT
- -- expander.
-
- elsif Attr_Id = Attribute_Enum_Rep then
- declare
- Exprs : constant List_Id := Expressions (N);
- begin
- if Is_Non_Empty_List (Exprs) then
- Expr := First (Exprs);
- else
- Expr := Prefix (N);
- end if;
-
- -- If the argument is a literal, expand it
-
- if Nkind (Expr) in N_Has_Entity
- and then Ekind (Entity (Expr)) = E_Enumeration_Literal
- then
- Exp_Attr.Expand_N_Attribute_Reference (N);
- end if;
- end;
-
elsif Attr_Id = Attribute_Object_Size
or else Attr_Id = Attribute_Size
or else Attr_Id = Attribute_Value_Size
--- gcc/ada/sem_attr.adb
+++ gcc/ada/sem_attr.adb
@@ -7719,7 +7719,11 @@ package body Sem_Attr is
-- purpose, a string literal counts as an object (attributes of string
-- literals can only appear in generated code).
- if Is_Object_Reference (P) or else Nkind (P) = N_String_Literal then
+ if Is_Object_Reference (P)
+ or else Nkind (P) = N_String_Literal
+ or else (Is_Entity_Name (P)
+ and then Ekind (Entity (P)) = E_Enumeration_Literal)
+ then
-- For Component_Size, the prefix is an array object, and we apply
-- the attribute to the type of the object. This is allowed for both
@@ -8533,7 +8537,7 @@ package body Sem_Attr is
--------------
when Attribute_Enum_Val => Enum_Val : declare
- Lit : Node_Id;
+ Lit : Entity_Id;
begin
-- We have something like Enum_Type'Enum_Val (23), so search for a