Open TheCalligrapher opened 1 week ago
According to [class.mem.general]/3 only enumerators of unscoped enumerations are members of the class.
[expr.ref]/6.5 establishes the meaning of the member access expression only for member enumerators.
However, [expr.ref]/6 also claims "Otherwise, one of the following rules applies." which doesn't seem to be true here. That looks like a defect to me. The suggested resolution for CWG 2902 would however clarify that this is ill-formed (because U::B
is not a member of the class).
@llvm/issue-subscribers-clang-frontend
Author: AndreyT (TheCalligrapher)
Note that the interpretation of the rules that allows the final example would also allow:
enum class E { a };
class B {} b;
E e = b.E::a;
(indeed that's basically the same thing as far as the language is concerned). [expr.ref]/7.5 doesn't say what happens here, for an E2 that is a non-member enumerator, so at best this is UB. But it seems appropriate to reject, as CWG2902's suggested resolution says.
Oh, I see. Thank you for the clarification. [class.mem.general]/3 does indeed make formal sense, even if the behavior might look "illogical" on the surface.
Sorry for the false alarm.
... However, it is possible to "dump" the enumerators from a scoped enum into the class scope by means of a using enum
declaration
struct S
{
enum class U { B };
using enum U;
};
With this combination of declarations Clang happily accepts s.B
syntax
S s;
s.B; // OK
which is not surprising, since this is basically the example from [enum.udecl]
.
But if I try referring to that B
through a qualified name after the dot operator (as U::B
or S::U::B
) Clang issues an error
S s;
s.U::B; // error: 'S::U::B' is not a member of class 'S'
s.S::U::B; // error: 'S::U::B' is not a member of class 'S'
Of course, this is a weird code, but still... are both of these really supposed to be erroneous? (GCC appears to accept all these variants.)
I do not see why the earlier reasoning shouldn't apply to s.B;
as well. B
is still not a member of the class and so this should also be ill-formed (or maybe technically UB as @zygoloid mentioned).
This seems to be an editorial issue in the standard. I have reported it here.
Here's the code sample that demonsrates the problem
All six lines that refer to enumerators from enums declared inside class
S
are perfectly valid. However, Clang issues an errorfor last one (i.e.
s.U::B
). Why?What makes it especially weird is that Clang has no problems with the qualified name in the
s.T::A
line, i.e. it does allow one to optionally use a qualified name to access enumerators from a "classic" unscoped enum (using qualified name with such enums is a possibility since C++11). However, for some unknown reason Clang rejects a similar attempt to access an enumerator from a scoped enum.GCC and MSVC++ have no issues with such code.