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.