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

--- Comment #4 from Steve Kargl <sgk at troutmask dot apl.washington.edu> ---
On Mon, Apr 27, 2020 at 06:27:25AM +0000, stefansf at linux dot ibm.com wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94769
> 
> --- Comment #3 from Stefan Schulze Frielinghaus <stefansf at linux dot 
> ibm.com> ---
> Since one call chain is gfc_resolve_dt -> check_io_constraints ->
> compare_to_allowed_values and at least one parameter of
> compare_to_allowed_values, from which the initialization of variable num
> depends, is passed through non-static function gfc_resolve_dt, the warning
> seems valid to me. Although compare_to_allowed_values is supposed to
> initialize num, it may return with a non-zero value although num is
> not initialized.
> 
compare_to_allowed_values() appears 25 times in io.c; once as
a prototype, once as the function, and 23 invocations.  This
is the function prototype:

compare_to_allowed_values (const char *specifier, const char *allowed[],
                           const char *allowed_f2003[],
                           const char *allowed_gnu[], gfc_char_t *value,
                           const char *statement, bool warn, locus *where,
                           int *num = NULL);

Of those 23 invocations, it is called once with a non-NULL &num argument.
That occurence is the one in question.  Here is the code:

      if (!compare_to_allowed_values
                 ("ASYNCHRONOUS", asynchronous, NULL, NULL,
                  dt->asynchronous->value.character.string,
                  io_kind_name (k), warn, &dt->asynchronous->where, &num))
         return false;

compare_to_allowed_values() returns either 0 or 1.  If it is 0,
then the if-statement will cause check_io_constraint() to return
false and num is never used.  If it returns 1, then one needs to
worry about num.

Prior to the invocation, it is noted that one has

 static const char *asynchronous[] = { "YES", "NO", NULL };

dt->asynchronous->value.character.string is the string parsed from
the Fortran program, e.g., OPEN(UNIT=10,FILE='foo', ASYNCHRONOUS='string')

The initial code in compare_to_allowed_values() is

  len = gfc_wide_strlen (value);
  if (len > 0)
    {
      for (len--; len > 0; len--)
        if (value[len] != ' ')
          break;
        len++;
    }

The above accounts for leading whitespace in value (aka
dt->asynchronous->value.character.string), and for a valid value of
ASYNCHRONOUS, len = 2 or 3.  The next chunk of code sets num for
a valid value.  Here allowed[] = asynchronous[].

  for (i = 0; allowed[i]; i++)
     if (len == strlen (allowed[i])
         && gfc_wide_strncasecmp (value, allowed[i], strlen (allowed[i])) == 0)
       {
         if (num)
           *num = i;
         return 1;
       }

If len does not equal 2 or 3, the block of code in the if statement is
not execute, num is not set, and the remainder of compare_to_allowed_values()
is executed, generating an error message, and returning 0.  A return of
0 means that num is not used in check_io_constraint as it returns false.

If len is equal to 2 or 3, then value is compared to "YES" and "NO".
If the comparison is true, then num (being a non-NULL pointer) has
it target set to either 0 or 1 (i.e., the  index of "YES" or "NO"
in allowed[]).  If the comparison is false, then the block of code in the
if statement is not execute, num is not set, and the remainder of
compare_to_allowed_values() is executed, generating an error message,
and returning 0.  A return of 0 means that num is not used in
check_io_constraint as it returns false.

In other words, a false positive.

There are now three choices.

1) Remove the command line option that causes the false positive.
2) Fix gcc to not generate a false positive.
3) Set num to anything you want to silence a false positive.

The above are the three options I offered in comment #1.

Reply via email to