https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121527
--- Comment #23 from Eric Botcazou <ebotcazou at gcc dot gnu.org> --- > I'm not exactly sure how so. For constant sizes you could use a > BIT_FIELD_REF, but for variable sizes there's no good alternative > (a V_C_E to a fake union plus component-ref maybe?). That said, > the upcasting is always to a same or smaller size type, it'll never > be a "paradoxical subreg", right? Yes, upcasting always shrinks the types and derived (tagged) types contain an explicit _Parent component of the parent type in Ada, so you can always build a COMPONENT_REF of it if the size is the same (or smaller). This at least passes ACATS and gnat.dg: diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc index f501915e82f..24a559c0c86 100644 --- a/gcc/ada/gcc-interface/utils.cc +++ b/gcc/ada/gcc-interface/utils.cc @@ -5145,8 +5145,13 @@ convert (tree type, tree expr) tree child_etype = etype; do { tree field = TYPE_FIELDS (child_etype); - if (DECL_NAME (field) == parent_name_id && TREE_TYPE (field) == type) - return build_component_ref (expr, field, false); + if (DECL_NAME (field) == parent_name_id) + { + if (TREE_TYPE (field) == type) + return build_component_ref (expr, field, false); + if (DECL_SIZE (field) == TYPE_SIZE (type)) + return convert (type, build_component_ref (expr, field, false)); + } child_etype = TREE_TYPE (field); } while (TREE_CODE (child_etype) == RECORD_TYPE); }