[cc65] Wrong handling of enum/struct/union types without member lists in local declarations
acqn opened this issue · comments
When a previous declaration that introduced the tag name of an enum(?)/struct/union is visible, only this one form out of all forms without their member lists as a local declaration redeclares a local enum(?)/struct/union type with the same tag name (that shadows the previous one) in the current scope:
struct TagName; /* <- enum(?)/struct/union type name terminated immediately with a semicolon */
Other forms without member lists just reuse the previous one without redeclaring any local types.
So with this example:
struct S { int a; } a;
void f(void)
{
extern struct S a; /* OK */
struct S s; /* WRONG: cc65 declares f::S that shadows <filescope>::S, but should just reuse <filescope>::S */
extern struct S a; /* OK */
{
extern struct S a; /* OK */
union S; /* WRONG: should be OK */
extern union S x; /* WRONG: should be OK */
union S { char b; } s; /* Recovered from previous errors, should be OK anyways */
}
}
void g(void)
{
struct S; /* OK: Declares g::S that shadows <filescope>::S */
extern struct S a; /* WRONG: should be an error redeclaring <filescope>::a of a different type */
}
Things get complicated when it comes to enum
. Pre-C23 compiler extensions that support forward declaration of enum
usually implement it similarly to struct
/union
. However, C23 requires it to be different from struct
/union
:
enum E { FIRST } c;
void h(void)
{
enum E; /* C23: No new type */
extern enum E c; /* C23: OK no conflicts */
}
The C23 way to actually shadow a previously visible filescope enum
with a new local enum
is to redeclare it with a fixed underlying type (or a member list, of course):
enum E { FIRST } c;
void h(void)
{
enum E : int; /* C23: h::E shadows <filescope>::E */
extern enum E c; /* C23: Error */
}