https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96024
Jakub Jelinek <jakub at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|RESOLVED |REOPENED
Resolution|FIXED |---
CC| |jakub at gcc dot gnu.org
--- Comment #17 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The new testcase seems to fail on big-endian hosts. I've analyzed this on 11
branch:
3190 /* For a constant string constructor, make sure the length is
3191 correct; truncate of fill with blanks if needed. */
3192 if (this_comp->ts.type == BT_CHARACTER &&
!this_comp->attr.allocatable
3193 && this_comp->ts.u.cl && this_comp->ts.u.cl->length
3194 && this_comp->ts.u.cl->length->expr_type == EXPR_CONSTANT
3195 && actual->expr->ts.type == BT_CHARACTER
3196 && actual->expr->expr_type == EXPR_CONSTANT)
3197 {
3198 ptrdiff_t c, e1;
3199 c = gfc_mpz_get_hwi
(this_comp->ts.u.cl->length->value.integer);
3200 e1 = actual->expr->value.character.length;
3201
3202 if (c != e1)
3203 {
3204 ptrdiff_t i, to;
3205 gfc_char_t *dest;
3206 dest = gfc_get_wide_string (c + 1);
*this_comp->ts.u.cl->length
$20 = {expr_type = EXPR_CONSTANT, ts = {type = BT_CHARACTER, kind = 1 ... }
Because it is a BT_CHARACTER EXPR_CONSTANTS, simplify_achar_char initialized it
as
813 result = gfc_get_character_expr (kind, &e->where, NULL, 1);
814 result->value.character.string[0] = mpz_get_ui (e->value.integer);
i.e. using the value.character union member.
But the code assumes it is an integral constant instead and uses value.integer
instead.
p this_comp->ts.u.cl->length->value.character
$22 = {length = 1, string = 0x2aa02ab2de0}
where string points to array of unsigned int, big endian, so contains value
0x00000001 followed by garbage, which happens to be 0, so bytes 0, 0, 0, 1, 0,
0, 0, 0
Now
p this_comp->ts.u.cl->length->value.integer
$23 = {{_mp_alloc = 0, _mp_size = 1, _mp_d = 0x2aa02ab2de0}}
(note, _mp_alloc and _mp_size are both 32-bit while length is 64-bit) and _mp_d
points to array of mp_limb_t, which is unsigned long.
So, this means c is 0x100000000 and we try to allocate 0x100000001 * 4 bytes ==
17179869188.
Now, on x86_64 string also points to array of unsigned int, but because it is
little endian, the value 1 is there 1, 0, 0, 0, 0, 0, 0, 0, 0 (the last 4 bytes
random garbage),
so c is 1 rather than 0x100000000 and it allocates 2 * 4 bytes.
So, presumably we need in addition to the
&& this_comp->ts.u.cl->length->expr_type == EXPR_CONSTANT
check also test that the constant uses value.integer union member rather than
some other one. Would
&& this_comp->ts.u.cl->length->ts.type == BT_INTEGER
be the right test for it or something else?