From: Eric Botcazou Date: Sat, 29 Jun 2019 08:22:35 +0000 (+0000) Subject: utils.c (unchecked_convert): Tweak comment. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=db53aa5c98f2698c11e74c755c78f9a32b15e28f;p=gcc.git utils.c (unchecked_convert): Tweak comment. * 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 --- diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 157ca3684d0..4db9b288212 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,9 @@ +2019-06-29 Eric Botcazou + + * 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 * gcc-interface/decl.c (gnat_to_gnu_entity) : If the diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 9da606e1494..c6942fe7761 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d2d59903dd3..aacf71c05ff 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-06-29 Eric Botcazou + + * gnat.dg/specs/unchecked_convert1.ads: New test. + * gnat.dg/specs/unchecked_convert2.ads: Likewise. + 2019-06-29 Eric Botcazou * 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 index 00000000000..53429cd38ff --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/unchecked_convert1.ads @@ -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 index 00000000000..8b04fc19541 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/unchecked_convert2.ads @@ -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;