Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cc65] cc65 extension on enumerator constants conflicted with C23 #2429

Open
acqn opened this issue Mar 3, 2024 · 3 comments
Open

[cc65] cc65 extension on enumerator constants conflicted with C23 #2429

acqn opened this issue Mar 3, 2024 · 3 comments
Labels

Comments

@acqn
Copy link
Contributor

acqn commented Mar 3, 2024

Points:

  • Each enumerator constant of the same enumeration may have different types during the definition of the enumeration until it is completed.
  • The allowed type of an enumerator constant without a = definition is limited:

During the processing of each enumeration constant in the enumerator list, the type of the enumera-
tion constant shall be
...
— the type of the value from the previous enumeration constant with one added to it. If such
an integer constant expression would overflow or wraparound the value of the previous
enumeration constant from the addition of one, the type takes on either:
— a suitably sized signed integer type, excluding the bit-precise signed integer types, capable
of representing the value of the previous enumeration constant plus one; or,
— a suitably sized unsigned integer type, excluding the bit-precise unsigned integer types,
capable of representing the value of the previous enumeration constant plus one.
A signed integer type is chosen if the previous enumeration constant being added is of signed
integer type
. An unsigned integer type is chosen if the previous enumeration constant is of
unsigned integer type
. If there is no suitably sized integer type described previously which
can represent the new value, then the enumeration has no type which can represent all its
values
.151)

— §6.7.2.2¶11, ISO/IEC 9899:2023 (E) working draft — April 1, 2023

enum E {
    e0 = 0x7FFF,     /* 'int' as always */
    e1,              /* 'unsigned int' in cc65, but 'long' according to C23 */
    s0 = sizeof e0,  /* s0 = 2 */
    s1 = sizeof e1,  /* cc65: s1 = 2 or C23: s1 = 4 */
    e2 = 0x7FFFFFFF, /* 'long' */
    //e3,            /* 'unsigned long' in cc65, but constraint violation (!) without 'long long' according to C23 */
};                   /* Now the enumerators shall have the same enumeration member type eg. 'long',
                        which is compatible with the underlying type of the enumeration */

_Static_assert(s0 == sizeof e0);              /* cc65: OK; C23: fail? */
_Static_assert(s1 == sizeof e1);              /* cc65: OK; C23: OK?  */
_Static_assert(sizeof e2 == sizeof (enum E)); /* cc65 & C23: OK */

Should the current behavior of cc65 be "fixed" or kept as-is?

BTW, this shows how annoying the "good old enumerations" are, even with (or thanks to) compiler extensions. Any interests in enumerations with fixed underlying types from C23?

@mrdudz
Copy link
Contributor

mrdudz commented Mar 3, 2024

Should the current behavior of cc65 be "fixed" or kept as-is?

I'm not 100% sure what this means (or what the difference between the cc65 extension and C23 would be) - however IF the fix means standard compliance (and "long" by default) then i think the cc65 mode should still used "unsigned ints" by default (longs are almost never what you really want on 6502 platforms).

But i might misunderstand.... :)

BTW, this shows how annoying the "good old enumerations" are, even with (or thanks to) compiler extensions. Any interests in enumerations with fixed underlying types from C23?

That sounds useful to me (ie there could be many applications for enums being chars instead of ints)

@mrdudz mrdudz added the cc65 label Mar 3, 2024
@acqn
Copy link
Contributor Author

acqn commented Mar 4, 2024

I'm not 100% sure what this means (or what the difference between the cc65 extension and C23 would be)

C23 requires the same signedness of an enumerator that is incremented from a previous one, whilst cc65 tries to use a type as small in size as possible.

In a 16-bit int env, the "integer rank promotion" for enumerators are:

  • C23: int -> long -> long long, unsigned int -> unsigned long -> unsigned long long
  • cc65: int -> unsigned int -> long -> unsigned long (no long long or unsigned long long)

The "integer rank promotion" goes on until the end of the enumerator list, where the finial decision on the enumerator type is made. That is to say, the type of each enumerator constant during processing the enumerator list may be different from that when the whole list is finished. And that is the reason why the value of sizeof e0 may change in the example.

@mrdudz
Copy link
Contributor

mrdudz commented Mar 17, 2024

C23 requires the same signedness of an enumerator that is incremented from a previous one, whilst cc65 tries to use a type as small in size as possible.

Ah, now i understand.

I see the desire to make it like C23 dictates. I also see how what cc65 currently does is useful in a 6510 context too....

I guess what i would prefer is, keep the way cc65 does it now when standard=cc65, and change it to C23 when it is not. Obviously i have no idea how much of a problem this would be in practise though :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants