> This is a regression from GCC 9 present on mainline and all active branches:
> the compilation of GtkAda in LTO mode trips on the assertion present in the
> fld_incomplete_type_of function about the TYPE_CANONICAL of types pointed
> to by pointer (or reference) types. The problem comes from an oversight in
> the update_pointer_to function on gcc-interface, which correctly propagates
> the TYPE_CANONICAL of the new pointer type to the old one when there is a
> new pointer type, but fails to synthesize it when there is no new pointer
> type.
>
> Tested on x86-64/Linux, applied on the mainline, 15 and 14 branches.
>
>
> 2025-12-15 Eric Botcazou <[email protected]>
>
> PR ada/123060
> * gcc-interface/utils.cc (update_pointer_to): Synthesize a new
> TYPE_CANONICAL for the old pointer type in the case where there
> is no new pointer type. Likewise for references.
The change incorrectly resets the alias set of the old pointer/reference,
which leads to the miscompilation of a few ACATS tests on some platforms.
Fixed thus, applied on the mainline, 15 and 14 branches.
PR ada/123060
* gcc-interface/utils.cc (update_pointer_to): Preserve the alias
sets present on the old pointer and old reference, if any.
--
Eric Botcazoudiff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
index 62587cdb91d..9176ec29d56 100644
--- a/gcc/ada/gcc-interface/utils.cc
+++ b/gcc/ada/gcc-interface/utils.cc
@@ -4680,15 +4680,24 @@ update_pointer_to (tree old_type, tree new_type)
/* If there is no pointer pointing to NEW_TYPE yet, re-compute the
TYPE_CANONICAL of the old pointer but pointing to NEW_TYPE, like
build_pointer_type would have done for such a pointer, because we
- will propagate it in the adjustment loop below. */
+ will propagate it in the adjustment loop below. But make sure to
+ preserve an alias set already present on the old pointer. */
if (TYPE_STRUCTURAL_EQUALITY_P (new_type))
SET_TYPE_STRUCTURAL_EQUALITY (old_ptr);
else if (TYPE_CANONICAL (new_type) != new_type
|| (TYPE_REF_CAN_ALIAS_ALL (old_ptr)
&& !lookup_attribute ("may_alias",
TYPE_ATTRIBUTES (new_type))))
- TYPE_CANONICAL (old_ptr)
- = build_pointer_type (TYPE_CANONICAL (new_type));
+ {
+ alias_set_type set;
+ if (TYPE_STRUCTURAL_EQUALITY_P (old_ptr))
+ set = TYPE_ALIAS_SET (old_ptr);
+ else
+ set = TYPE_ALIAS_SET (TYPE_CANONICAL (old_ptr));
+ TYPE_CANONICAL (old_ptr)
+ = build_pointer_type (TYPE_CANONICAL (new_type));
+ TYPE_ALIAS_SET (TYPE_CANONICAL (old_ptr)) = set;
+ }
}
/* Now adjust them. */
@@ -4716,15 +4725,24 @@ update_pointer_to (tree old_type, tree new_type)
/* If there is no reference pointing to NEW_TYPE yet, re-compute the
TYPE_CANONICAL of the old reference but pointing to NEW_TYPE, like
build_reference_type would have done for such a reference, because
- we will propagate it in the adjustment loop below. */
+ we will propagate it in the adjustment loop below. But make sure
+ to preserve an alias set already present on the old reference. */
if (TYPE_STRUCTURAL_EQUALITY_P (new_type))
SET_TYPE_STRUCTURAL_EQUALITY (old_ref);
else if (TYPE_CANONICAL (new_type) != new_type
|| (TYPE_REF_CAN_ALIAS_ALL (old_ref)
&& !lookup_attribute ("may_alias",
TYPE_ATTRIBUTES (new_type))))
- TYPE_CANONICAL (old_ref)
- = build_reference_type (TYPE_CANONICAL (new_type));
+ {
+ alias_set_type set;
+ if (TYPE_STRUCTURAL_EQUALITY_P (old_ref))
+ set = TYPE_ALIAS_SET (old_ref);
+ else
+ set = TYPE_ALIAS_SET (TYPE_CANONICAL (old_ref));
+ TYPE_CANONICAL (old_ref)
+ = build_reference_type (TYPE_CANONICAL (new_type));
+ TYPE_ALIAS_SET (TYPE_CANONICAL (old_ref)) = set;
+ }
}
/* Now adjust them. */