https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120196

            Bug ID: 120196
           Summary: In findloc2_s* when "back" is true loop goes one more
                    step than needed.
           Product: gcc
           Version: 15.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libfortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: daniil2472s at gmail dot com
  Target Milestone: ---

Greetings!

Found a bug that actually doesn't have any effects in tests.

In findloc2_s1.c, findloc2_s4.c, and corresponding ifindloc2.m4, there are two
functions, findloc2_s* and mfindloc2_s*, with the following problem.

When "back" is true loop goes one more step than needed.

$ cat /libgfortran/generated/findloc2_s1.c
...
index_type
findloc2_s1 (gfc_array_s1 * const restrict array, const GFC_UINTEGER_1 *
restrict value,
                      GFC_LOGICAL_4 back,
                      gfc_charlen_type len_array, gfc_charlen_type len_value)
...
  if (back)
    {
      src = array->base_addr + (extent - 1) * sstride;
      for (i = extent; i >= 0; i--)
        {
          if (compare_string (len_array, (char *) src, len_value, (char *)
value) == 0)
            return i;
          src -= sstride;
        }
    }
  else
    {
      src = array->base_addr;
      for (i = 1; i <= extent; i++)
        {
          if (compare_string (len_array, (char *) src, len_value, (char *)
value) == 0)
            return i;
          src += sstride;
        }
    }
...

Please note following string: 
for (i = extent; i >= 0; i--)
It must be constraints with i >= 1 or i > 0.

I couldn't create any test that failed due to the mistake, because when the
required value lies beyond the string bound, the function returns 0, like it
hasn't found any value. To prove that there are mistakes, we can count the
number of steps when "back" is false or compare with other findlocs.

For example:
$ cat findloc1_i4.c
...
extern void
findloc1_i4 (gfc_array_index_type * const restrict retarray,
            gfc_array_i4 * const restrict array, GFC_INTEGER_4 value,
            const index_type * restrict pdim, GFC_LOGICAL_4 back)
...
      if (back)
        {
          src = base + (len - 1) * delta * 1;
          for (n = len; n > 0; n--, src -= delta * 1)
            {
              if (*src == value)
                {
                  result = n;
                  break;
                }
            }
        }
      else
        {
          src = base;
          for (n = 1; n <= len; n++, src += delta * 1)
            {
              if (*src == value)
                {
                  result = n;
                  break;
                }
            }
        }
...

Reply via email to