sem_attr.adb (Analyze_Attribute): Allow any expression of discrete type.
authorBob Duff <duff@adacore.com>
Wed, 6 Jul 2016 12:32:35 +0000 (12:32 +0000)
committerArnaud Charlet <charlet@gcc.gnu.org>
Wed, 6 Jul 2016 12:32:35 +0000 (14:32 +0200)
2016-07-06  Bob Duff  <duff@adacore.com>

* sem_attr.adb (Analyze_Attribute): Allow any expression of
discrete type.
* exp_attr.adb (Expand_N_Attribute_Reference): Change the
constant-folding code to correctly handle cases newly allowed
by Analyze_Attribute.

From-SVN: r238042

gcc/ada/ChangeLog
gcc/ada/exp_attr.adb
gcc/ada/sem_attr.adb

index 9ddf035e6988ec0d3a6ccb7918c0ce20bdc20840..9a16f81a4ba3959217cc25aee9ca2b465fd9e628 100644 (file)
@@ -1,3 +1,11 @@
+2016-07-06  Bob Duff  <duff@adacore.com>
+
+       * sem_attr.adb (Analyze_Attribute): Allow any expression of
+       discrete type.
+       * exp_attr.adb (Expand_N_Attribute_Reference): Change the
+       constant-folding code to correctly handle cases newly allowed
+       by Analyze_Attribute.
+
 2016-07-05  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc-interface/decl.c (gnat_to_gnu_entity): Invoke global_bindings_p
index 6c5f3b5e7c5f42279915e6a3c94a2b323a3fa837..47cee2b6af2b2d648132f7583c7c38d6648bdc80 100644 (file)
@@ -3007,50 +3007,57 @@ package body Exp_Attr is
       -- Enum_Rep --
       --------------
 
-      when Attribute_Enum_Rep => Enum_Rep :
+      when Attribute_Enum_Rep => Enum_Rep : declare
+         Expr : Node_Id;
       begin
-         --  X'Enum_Rep (Y) expands to
-
-         --    target-type (Y)
-
-         --  This is simply a direct conversion from the enumeration type to
-         --  the target integer type, which is treated by the back end as a
-         --  normal integer conversion, treating the enumeration type as an
-         --  integer, which is exactly what we want. We set Conversion_OK to
-         --  make sure that the analyzer does not complain about what otherwise
-         --  might be an illegal conversion.
+         --  Get the expression, which is X for Enum_Type'Enum_Rep (X)
+         --  or X'Enum_Rep.
 
          if Is_Non_Empty_List (Exprs) then
-            Rewrite (N,
-              OK_Convert_To (Typ, Relocate_Node (First (Exprs))));
+            Expr := First (Exprs);
+         else
+            Expr := Pref;
+         end if;
 
-         --  X'Enum_Rep where X is an enumeration literal is replaced by
-         --  the literal value.
+         --  If the expression is an enumeration literal, it is
+         --  replaced by the literal value.
 
-         elsif Ekind (Entity (Pref)) = E_Enumeration_Literal then
+         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 (Pref))));
+              Make_Integer_Literal (Loc, Enumeration_Rep (Entity (Expr))));
 
          --  If this is a renaming of a literal, recover the representation
          --  of the original. If it renames an expression there is nothing
          --  to fold.
 
-         elsif Ekind (Entity (Pref)) = E_Constant
-           and then Present (Renamed_Object (Entity (Pref)))
-           and then Is_Entity_Name (Renamed_Object (Entity (Pref)))
-           and then Ekind (Entity (Renamed_Object (Entity (Pref)))) =
+         elsif Nkind (Expr) in N_Has_Entity
+           and then Ekind (Entity (Expr)) = E_Constant
+           and then Present (Renamed_Object (Entity (Expr)))
+           and then Is_Entity_Name (Renamed_Object (Entity (Expr)))
+           and then Ekind (Entity (Renamed_Object (Entity (Expr)))) =
                       E_Enumeration_Literal
          then
             Rewrite (N,
               Make_Integer_Literal (Loc,
-                Enumeration_Rep (Entity (Renamed_Object (Entity (Pref))))));
+                Enumeration_Rep (Entity (Renamed_Object (Entity (Expr))))));
+
+         --  If not constant-folded above, Enum_Type'Enum_Rep (X) or
+         --  X'Enum_Rep expands to
 
-         --  X'Enum_Rep where X is an object does a direct unchecked conversion
-         --  of the object value, as described for the type case above.
+         --    target-type (X)
+
+         --  This is simply a direct conversion from the enumeration type to
+         --  the target integer type, which is treated by the back end as a
+         --  normal integer conversion, treating the enumeration type as an
+         --  integer, which is exactly what we want. We set Conversion_OK to
+         --  make sure that the analyzer does not complain about what otherwise
+         --  might be an illegal conversion.
 
          else
             Rewrite (N,
-              OK_Convert_To (Typ, Relocate_Node (Pref)));
+              OK_Convert_To (Typ, Relocate_Node (Expr)));
          end if;
 
          Set_Etype (N, Typ);
index d6d850994be0420d38eba1b8874b5ba13eb3c9f2..a05ad7e5532fe0ec82aa768943b799b92192a38e 100644 (file)
@@ -3742,16 +3742,8 @@ package body Sem_Attr is
             Check_E1;
             Check_Discrete_Type;
             Resolve (E1, P_Base_Type);
-
-         else
-            if not Is_Entity_Name (P)
-              or else (not Is_Object (Entity (P))
-                        and then Ekind (Entity (P)) /= E_Enumeration_Literal)
-            then
-               Error_Attr_P
-                 ("prefix of % attribute must be " &
-                  "discrete type/object or enum literal");
-            end if;
+         elsif not Is_Discrete_Type (Etype (P)) then
+            Error_Attr_P ("prefix of % attribute must be of discrete type");
          end if;
 
          Set_Etype (N, Universal_Integer);