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.

Reply via email to