[Ada] Move folding of unchecked conversions from expansion to evaluation
authorPiotr Trojanek <trojanek@adacore.com>
Mon, 30 Nov 2020 15:56:38 +0000 (16:56 +0100)
committerPierre-Marie de Rodat <derodat@adacore.com>
Thu, 17 Dec 2020 10:49:22 +0000 (05:49 -0500)
gcc/ada/

* exp_ch4.adb (Expand_N_Unchecked_Type_Conversion): Remove
folding of discrete values.
* exp_intr.adb (Expand_Unc_Conversion): Analyze, resolve and
evaluate (if possible) calls to instances of
Ada.Unchecked_Conversion after they have been expanded into
N_Unchecked_Type_Conversion.
* sem_eval.adb (Eval_Unchecked_Conversion): Add folding of
discrete values.

gcc/ada/exp_ch4.adb
gcc/ada/exp_intr.adb
gcc/ada/sem_eval.adb

index 91ae71efd211c1e2e866d5b39da1a0742f3fad1f..e376648a4a50822e8536d5aba325924ee2fe8e3f 100644 (file)
@@ -12815,56 +12815,6 @@ package body Exp_Ch4 is
          return;
       end if;
 
-      --  If we have a conversion of a compile time known value to a target
-      --  type and the value is in range of the target type, then we can simply
-      --  replace the construct by an integer literal of the correct type. We
-      --  only apply this to discrete types being converted. Possibly it may
-      --  apply in other cases, but it is too much trouble to worry about.
-
-      --  Note that we do not do this transformation if the Kill_Range_Check
-      --  flag is set, since then the value may be outside the expected range.
-      --  This happens in the Normalize_Scalars case.
-
-      --  We also skip this if either the target or operand type is biased
-      --  because in this case, the unchecked conversion is supposed to
-      --  preserve the bit pattern, not the integer value.
-
-      if Is_Integer_Type (Target_Type)
-        and then not Has_Biased_Representation (Target_Type)
-        and then Is_Discrete_Type (Operand_Type)
-        and then not Has_Biased_Representation (Operand_Type)
-        and then Compile_Time_Known_Value (Operand)
-        and then not Kill_Range_Check (N)
-      then
-         declare
-            Val : constant Uint := Expr_Rep_Value (Operand);
-
-         begin
-            if Compile_Time_Known_Value (Type_Low_Bound (Target_Type))
-                 and then
-               Compile_Time_Known_Value (Type_High_Bound (Target_Type))
-                 and then
-               Val >= Expr_Value (Type_Low_Bound (Target_Type))
-                 and then
-               Val <= Expr_Value (Type_High_Bound (Target_Type))
-            then
-               Rewrite (N, Make_Integer_Literal (Sloc (N), Val));
-
-               --  If Address is the target type, just set the type to avoid a
-               --  spurious type error on the literal when Address is a visible
-               --  integer type.
-
-               if Is_Descendant_Of_Address (Target_Type) then
-                  Set_Etype (N, Target_Type);
-               else
-                  Analyze_And_Resolve (N, Target_Type);
-               end if;
-
-               return;
-            end if;
-         end;
-      end if;
-
       --  Generate an extra temporary for cases unsupported by the C backend
 
       if Modify_Tree_For_C then
index 7fc00c706f2c7490c3816da3617c5998718c3975..3be039b4be5de626f1b600fbb9781602ebcdf003 100644 (file)
@@ -29,7 +29,6 @@ with Einfo;    use Einfo;
 with Elists;   use Elists;
 with Expander; use Expander;
 with Exp_Atag; use Exp_Atag;
-with Exp_Ch4;  use Exp_Ch4;
 with Exp_Ch7;  use Exp_Ch7;
 with Exp_Ch11; use Exp_Ch11;
 with Exp_Code; use Exp_Code;
@@ -857,7 +856,7 @@ package body Exp_Intr is
    ---------------------------
 
    procedure Expand_Unc_Conversion (N : Node_Id; E : Entity_Id) is
-      Func : constant Entity_Id  := Entity (Name (N));
+      Func : constant Entity_Id := Entity (Name (N));
       Conv : Node_Id;
       Ftyp : Entity_Id;
       Ttyp : Entity_Id;
@@ -908,12 +907,7 @@ package body Exp_Intr is
       end if;
 
       Rewrite (N, Unchecked_Convert_To (Ttyp, Conv));
-      Set_Etype (N, Ttyp);
-      Set_Analyzed (N);
-
-      if Nkind (N) = N_Unchecked_Type_Conversion then
-         Expand_N_Unchecked_Type_Conversion (N);
-      end if;
+      Analyze_And_Resolve (N, Ttyp);
    end Expand_Unc_Conversion;
 
    -----------------------------
index 68498e6caaf0e3fdf1d5991f0779303ac20730b3..1a832f767cd9a1113d8a57986ec4efc089948f37 100644 (file)
@@ -4359,8 +4359,62 @@ package body Sem_Eval is
    --  processing is to check for a non-static context for the operand.
 
    procedure Eval_Unchecked_Conversion (N : Node_Id) is
+      Target_Type  : constant Entity_Id := Etype (N);
+      Operand      : constant Node_Id   := Expression (N);
+      Operand_Type : constant Entity_Id := Etype (Operand);
+
    begin
-      Check_Non_Static_Context (Expression (N));
+      Check_Non_Static_Context (Operand);
+
+      --  If we have a conversion of a compile time known value to a target
+      --  type and the value is in range of the target type, then we can simply
+      --  replace the construct by an integer literal of the correct type. We
+      --  only apply this to discrete types being converted. Possibly it may
+      --  apply in other cases, but it is too much trouble to worry about.
+
+      --  Note that we do not do this transformation if the Kill_Range_Check
+      --  flag is set, since then the value may be outside the expected range.
+      --  This happens in the Normalize_Scalars case.
+
+      --  We also skip this if either the target or operand type is biased
+      --  because in this case, the unchecked conversion is supposed to
+      --  preserve the bit pattern, not the integer value.
+
+      if Is_Integer_Type (Target_Type)
+        and then not Has_Biased_Representation (Target_Type)
+        and then Is_Discrete_Type (Operand_Type)
+        and then not Has_Biased_Representation (Operand_Type)
+        and then Compile_Time_Known_Value (Operand)
+        and then not Kill_Range_Check (N)
+      then
+         declare
+            Val : constant Uint := Expr_Rep_Value (Operand);
+
+         begin
+            if Compile_Time_Known_Value (Type_Low_Bound (Target_Type))
+                 and then
+               Compile_Time_Known_Value (Type_High_Bound (Target_Type))
+                 and then
+               Val >= Expr_Value (Type_Low_Bound (Target_Type))
+                 and then
+               Val <= Expr_Value (Type_High_Bound (Target_Type))
+            then
+               Rewrite (N, Make_Integer_Literal (Sloc (N), Val));
+
+               --  If Address is the target type, just set the type to avoid a
+               --  spurious type error on the literal when Address is a visible
+               --  integer type.
+
+               if Is_Descendant_Of_Address (Target_Type) then
+                  Set_Etype (N, Target_Type);
+               else
+                  Analyze_And_Resolve (N, Target_Type);
+               end if;
+
+               return;
+            end if;
+         end;
+      end if;
    end Eval_Unchecked_Conversion;
 
    --------------------