utils.c (unchecked_convert): Tweak comment.
authorEric Botcazou <ebotcazou@adacore.com>
Sat, 29 Jun 2019 08:22:35 +0000 (08:22 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Sat, 29 Jun 2019 08:22:35 +0000 (08:22 +0000)
* gcc-interface/utils.c (unchecked_convert): Tweak comment.  Only skip
dereferences when padding to have the same size on both sides.  Do it
for destination types with self-referential size too.

From-SVN: r272821

gcc/ada/ChangeLog
gcc/ada/gcc-interface/utils.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/specs/unchecked_convert1.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/specs/unchecked_convert2.ads [new file with mode: 0644]

index 157ca3684d001ef2022b8e0d0e27f4a05c5b54c4..4db9b2882127568b51093cbdd46bb25713209623 100644 (file)
@@ -1,3 +1,9 @@
+2019-06-29  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc-interface/utils.c (unchecked_convert): Tweak comment.  Only skip
+       dereferences when padding to have the same size on both sides.  Do it
+       for destination types with self-referential size too.
+
 2019-06-29  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Type>: If the
index 9da606e1494d13c93e2b051d4ed3b3f0088437f8..c6942fe7761a72de2e22b4e00f03a5be27b97e48 100644 (file)
@@ -5265,8 +5265,8 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
   if (etype == type)
     return expr;
 
-  /* If both types are integral just do a normal conversion.
-     Likewise for a conversion to an unconstrained array.  */
+  /* If both types are integral or regular pointer, then just do a normal
+     conversion.  Likewise for a conversion to an unconstrained array.  */
   if (((INTEGRAL_TYPE_P (type)
        || (POINTER_TYPE_P (type) && !TYPE_IS_THIN_POINTER_P (type))
        || (code == RECORD_TYPE && TYPE_JUSTIFIED_MODULAR_P (type)))
@@ -5397,14 +5397,16 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
      we need to pad to have the same size on both sides.
 
      ??? We cannot do it unconditionally because unchecked conversions are
-     used liberally by the front-end to implement polymorphism, e.g. in:
+     used liberally by the front-end to implement interface thunks:
 
+       type ada__tags__addr_ptr is access system.address;
        S191s : constant ada__tags__addr_ptr := ada__tags__addr_ptr!(S190s);
        return p___size__4 (p__object!(S191s.all));
 
-     so we skip all expressions that are references.  */
-  else if (!REFERENCE_CLASS_P (expr)
+     so we need to skip dereferences.  */
+  else if (!INDIRECT_REF_P (expr)
           && !AGGREGATE_TYPE_P (etype)
+          && ecode != UNCONSTRAINED_ARRAY_TYPE
           && TREE_CONSTANT (TYPE_SIZE (type))
           && (c = tree_int_cst_compare (TYPE_SIZE (etype), TYPE_SIZE (type))))
     {
@@ -5424,6 +5426,31 @@ unchecked_convert (tree type, tree expr, bool notrunc_p)
        }
     }
 
+  /* Likewise if we are converting from a scalar type to a type with self-
+     referential size.  We use the max size to do the padding in this case.  */
+  else if (!INDIRECT_REF_P (expr)
+          && !AGGREGATE_TYPE_P (etype)
+          && ecode != UNCONSTRAINED_ARRAY_TYPE
+          && CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type)))
+    {
+      tree new_size = max_size (TYPE_SIZE (type), true);
+      c = tree_int_cst_compare (TYPE_SIZE (etype), new_size);
+      if (c < 0)
+       {
+         expr = convert (maybe_pad_type (etype, new_size, 0, Empty,
+                                         false, false, false, true),
+                         expr);
+         expr = unchecked_convert (type, expr, notrunc_p);
+       }
+      else
+       {
+         tree rec_type = maybe_pad_type (type, TYPE_SIZE (etype), 0, Empty,
+                                         false, false, false, true);
+         expr = unchecked_convert (rec_type, expr, notrunc_p);
+         expr = build_component_ref (expr, TYPE_FIELDS (rec_type), false);
+       }
+    }
+
   /* We have a special case when we are converting between two unconstrained
      array types.  In that case, take the address, convert the fat pointer
      types, and dereference.  */
index d2d59903dd3e5fd1b865a24b6f5f2295e29e7c68..aacf71c05ff7cde85d228f8c5ceabcf2ac405f0c 100644 (file)
@@ -1,3 +1,8 @@
+2019-06-29  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/specs/unchecked_convert1.ads: New test.
+       * gnat.dg/specs/unchecked_convert2.ads: Likewise.
+
 2019-06-29  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/specs/size_clause3.ads: Adjust error message.
diff --git a/gcc/testsuite/gnat.dg/specs/unchecked_convert1.ads b/gcc/testsuite/gnat.dg/specs/unchecked_convert1.ads
new file mode 100644 (file)
index 0000000..53429cd
--- /dev/null
@@ -0,0 +1,20 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+
+with Ada.Unchecked_Conversion;
+with System;
+
+package Unchecked_Convert1 is
+
+  type Rec (D : Boolean := False) is record
+    case D is
+      when True => I : Integer;
+      when False => null;
+    end case;
+  end record;
+
+  function To_Rec is new Ada.Unchecked_Conversion (System.Address, Rec);
+
+  function F (A : System.Address) return Rec is (To_Rec (A));
+
+end Unchecked_Convert1;
diff --git a/gcc/testsuite/gnat.dg/specs/unchecked_convert2.ads b/gcc/testsuite/gnat.dg/specs/unchecked_convert2.ads
new file mode 100644 (file)
index 0000000..8b04fc1
--- /dev/null
@@ -0,0 +1,19 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+
+with Ada.Unchecked_Conversion;
+
+package Unchecked_Convert2 is
+
+  type Address is access String;
+  for Address'Size use Standard'Address_Size;
+
+  type Rec is record
+    A : Address;
+  end record;
+
+  function To_Integer is new Ada.Unchecked_Conversion (Address, Integer);
+
+  function F (R : Rec) return Integer is (To_Integer (R.A));
+
+end Unchecked_Convert2;