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

Enum tag not in scope inside its (fixed underlying) enum type specifier #70605

Open
alexshpilkin opened this issue Oct 29, 2023 · 6 comments
Open
Labels
c23 clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party

Comments

@alexshpilkin
Copy link

Quoth C23 draft N3096 in 6.2.1p7 (I haven’t seen the more recent but paywalled N3149):

Structure, union, and enumeration tags have scope that begins just after the appearance of the tag in a type specifier that declares the tag.

In Clang trunk with -std=c23 as well as Clang 16.0.6 with -std=c2x, on the other hand, I can refer to the enclosing scope’s definition of the tag being declared inside the enum-type-specifier, even though I wouldn’t have been able to do that later inside the enumerator-list:

struct foo { int x; };
void bar(void) { enum foo : typeof(((struct foo *)0)->x); }
// void baz(void) { enum foo { A = sizeof(((struct foo *)0)->x) }; }
// ^^^ error: use of 'foo' with tag type that does not match previous declaration

So this looks to be wrong as far as C23 is concerned. Replacing typeof by decltype, I also see this being accepted in C++ mode with -std=c++11, c++14, c++17 and c++20. I don’t know if that’s correct for C++, but I would be surprised if so, because it’s certainly inconsistent with how the typical instance of the CRTP works.

See also #57836 re this feature in C generally.

@alexshpilkin alexshpilkin changed the title Enum not in scope inside its (fixed underlying) enum type specifier Enum tag not in scope inside its (fixed underlying) enum type specifier Oct 29, 2023
@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" c++23 and removed new issue labels Oct 30, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Oct 30, 2023

@llvm/issue-subscribers-clang-frontend

Author: Alex Shpilkin (alexshpilkin)

Quoth C23 draft [N3096](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf) in 6.2.1p7 (I haven’t seen the more recent but paywalled N3149):

> Structure, union, and enumeration tags have scope that begins just after the appearance of the tag in a type specifier that declares the tag.

In Clang trunk with -std=c23 as well as Clang 16.0.6 with -std=c2x, on the other hand, I can refer to the enclosing scope’s definition of the tag being declared inside the enum-type-specifier, even though I wouldn’t have been able to do that later inside the enumerator-list:

struct foo { int x; };
void bar(void) { enum foo : typeof(((struct foo *)0)->x); }
// void baz(void) { enum foo { A = sizeof(((struct foo *)0)->x) }; }
// ^^^ error: use of 'foo' with tag type that does not match previous declaration

So this looks to be wrong as far as C23 is concerned. Replacing typeof by decltype, I also see this being accepted in C++ mode with -std=c++11, c++14, c++17 and c++20. I don’t know if that’s correct for C++, but I would be surprised if so, because it’s certainly inconsistent with how the typical instance of the CRTP works.

See also #57836 re this feature in C generally.

@shafik
Copy link
Collaborator

shafik commented Oct 30, 2023

CC @AaronBallman

@alexshpilkin
Copy link
Author

@EugeneZelenko Is this the correct label? I meant to primarily refer to C23, not C++23. If this applies to C++ as well (needs to be checked in the standard, which I’m not really capable of doing), then I’d expect it to be relevant for C++11 and later, not C++23 specifically.

@EugeneZelenko EugeneZelenko added c23 and removed c++23 labels Oct 30, 2023
@EugeneZelenko
Copy link
Contributor

@alexshpilkin: Sorry for my mistake.

@AaronBallman AaronBallman added the confirmed Verified by a second party label Oct 31, 2023
@AaronBallman
Copy link
Collaborator

There is a bug here but it's not what the OP expects, unfortunately. We should be rejecting the declarations in both bar() and baz(), not just the one in baz(). This is DR129 which still holds true today. C23 6.2.3p1 specifies that all tags occupy the same name space even though there are three separate tags. C23 6.7.2.3p1 then makes it a constraint violation because the same tag (which is the identifier used to name the type) is used with a different choice of struct, union, or enum.

GCC and ICC have the correct behavior in this case: https://godbolt.org/z/4T7fbPden

@alexshpilkin
Copy link
Author

Uh, I wrote this around 12am and might not have been very clear, but very much wanted both bar() and baz() to be rejected, yes :) Using struct foo just seemed like an expedient way to show that Clang thought enum foo wasn’t in scope until after the brace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c23 clang:frontend Language frontend issues, e.g. anything involving "Sema" confirmed Verified by a second party
Projects
None yet
Development

No branches or pull requests

5 participants