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

            Bug ID: 121406
           Summary: Type compatibility checks between old-style function
                    definition and prototyped function type ignore
                    parameters
           Product: gcc
           Version: 15.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: stephenheumann at gmail dot com
  Target Milestone: ---

gcc -std=c17 -pedantic will compile this with no diagnostics:

```
void f(a,b)
int a;
long b;
{}

void (*p1)(int) = &f; /* mismatched number of parameters */
void (*p2)(int,double) = &f; /* mismatched parameter types */
```

Based on the definition of type compatibility for function types in C89 through
C17, the type of f is incompatible with the types of *p1 and *p2 because they
disagree in the number or type of parameters, and thus diagnostics should be
produced for the two initializations, but GCC does not produce any.  When
checking compatibility with the prototyped function types, GCC seems to ignore
the number and type of parameters from the old-style function definition, which
is contrary to the standards.

For reference, C17 6.7.6.3 p15 specifies the rules for type compatibility
between a function type given by an old-style function definition and a
prototyped function type as follows:

"For two function types to be compatible, both shall specify compatible return
types. [...] If one type has a parameter type list and the other type is
specified by a function definition that contains a (possibly empty) identifier
list, both shall agree in the number of parameters, and the type of each
prototype parameter shall be compatible with the type that results from the
application of the default argument promotions to the type of the corresponding
identifier."

(C89 through C17 all contain similar language.)

Apart from missing diagnostics, GCC's non-standard type compatibility behavior
can cause the wrong association to be selected in _Generic, like in the
following example:

```
void f(a,b)
int a;
long b;
{}

int main(void) {
        return _Generic(&f, void (*)(int): 1, default: 0);
}
```

When compiled by GCC, this program returns 1, but it should return 0.

Reply via email to