cc65: Erroneous error for K & R function definitions with enum parameters
This gives an error with --standard c89, but should be OK:
enum E { I };
extern int f(enum E);
int f(e) 
  enum E e;
{
  return 1;
}
% cc65 --standard c89 /tmp/func3.c
/tmp/func3.c(5): Error: Conflicting function types for 'f'
/tmp/func3.c(7): Warning: Parameter 'e' is never used
1 errors and 1 warnings generated.
This works with gcc, and used to work with cc65. gcc godbolt old cc65 godbolt
I didn’t try to bisect, but maybe one of @acqn’s function handling changes broke this.
It would also be nice if the error message said what the compiler thought the conflicting types were.
The line numbers are also a bit strange, since lines 5 and 7 are the opening and closing curly braces, respectively.
About this issue
- Original URL
 - State: closed
 - Created 4 years ago
 - Comments: 15 (15 by maintainers)
 
Commits related to this issue
- added test related to issue #1263 — committed to cc65/cc65 by mrdudz 4 years ago
 - Fixed test case for Issue #1263. — committed to acqn/cc65 by acqn 3 years ago
 - Fixed test case for Issue #1263. — committed to cc65/cc65 by acqn 3 years ago
 
Wow that’s a lot to reply to. So I’ll break down into several posts.
The goal is to get to make clear what is the problem and how to resolve that, right? 😉
So let’s start with the “old K & R style” topic:
@mrdudz
No, I don’t think so. It reads to me that the prototype form doesn’t do that promotion for comparison, but only the “old K & R form” does.
@greg-king5
There are some statements with an example in the standard text (https://port70.net/~nsz/c/c89/c89-draft.html#3.7.1) that disagree, if I don’t misinterpret them:
Semantics
The declarator in a function definition specifies the name of the function being defined and the identifiers of its parameters. If the declarator includes a parameter type list, the list also specifies the types of all the parameters; such a declarator also serves as a function prototype for later calls to the same function in the same translation unit. If the declarator includes an identifier list, the types of the parameters may be declared in a following declaration list. Any parameter that is not declared has type int .
…
Examples
Here extern is the storage-class specifier and int is the type specifier (each of which may be omitted as those are the defaults); max(int a, int b) is the function declarator; and
is the function body. The following similar definition uses the identifier-list form for the parameter declarations:
Here int a, b; is the declaration list for the parameters, which may be omitted because those are the defaults. The difference between these two definitions is that the first form acts as a prototype declaration that forces conversion of the arguments of subsequent calls to the function, whereas the second form may not.
That’s to say, the identifier-list form is not a parameter type list, even if the former had all types of the parameters specified.