https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106557
anlauf at gcc dot gnu.org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |anlauf at gcc dot gnu.org Ever confirmed|0 |1 Status|UNCONFIRMED |NEW Last reconfirmed| |2022-08-18 --- Comment #1 from anlauf at gcc dot gnu.org --- Confirmed. The underlying issue also affects ibclr, and possibly other intrinsics that are simplified at compile time. Reduced testcase: print *, ibset (transfer (0, 0) , 0) ! bad print *, ibset (transfer (0, 0) + 0, 0) ! OK print *, ibset (transfer (0, 0) , 0) + 0 ! OK print *, transfer (ibset (transfer (0, 0), 0), 0) == 1 ! bad print *, transfer (ibclr (transfer (1, 0), 0), 0) == 0 ! bad end The problem arises from the dual representation of the result of the simplification of TRANSFER in gfc_simplify_transfer(), once as result->value.integer, and as result->representation.string. The latter is used e.g. for ensuring safe round-trip for nested TRANSFER(TRANSFER(...),...). It happens in gfc_simplify_ibset that value.integer is updated, but not representation.string, and under the given circumstances either one or the other is used later. Possible solutions: 1) conservative hack: diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc index fb725994653..6c5ffcdaf86 100644 --- a/gcc/fortran/simplify.cc +++ b/gcc/fortran/simplify.cc @@ -3380,6 +3380,11 @@ gfc_simplify_ibclr (gfc_expr *x, gfc_expr *y) k = gfc_validate_kind (x->ts.type, x->ts.kind, false); result = gfc_copy_expr (x); + if (result->representation.string) + { + free (result->representation.string); + result->representation.string = NULL; + } convert_mpz_to_unsigned (result->value.integer, gfc_integer_kinds[k].bit_size); and a similar change to gfc_simplify_ibset. This fixes the issue just for those two intrinsics. This may miss other cases, although I could not find them so far. 2) more aggressive hack: diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc index fb725994653..3e895e12f8c 100644 --- a/gcc/fortran/simplify.cc +++ b/gcc/fortran/simplify.cc @@ -8157,6 +8158,16 @@ gfc_simplify_transfer (gfc_expr *source, gfc_expr *mold, gfc_expr *size) /* And read the buffer back into the new expression. */ gfc_target_interpret_expr (buffer, buffer_size, result, false); + /* Integer is capable to hold all bits needed for complete round-trip + with TRANSFER-in-TRANSFER. Drop separate memory representation so that + subsequent simplification of bit manipulation intrinsics of the result + of gfc_simplify_transfer does not lead to inconsistencies. */ + if (result->ts.type == BT_INTEGER) + { + free (result->representation.string); + result->representation.string = NULL; + } + return result; } Both patches regtest cleanly on x86_64-pc-linux-gnu.