In case of use strongly typed enumS as bit fields of structS in C++0x mode, compiler says "bit-field 'smth' with non-integral type". Though, the standard says "A bit-field shall have integral or enumeration type (3.9.1)."
In future please provide a complete testcase, as requested at http://gcc.gnu.org/bugs Testcase reduced from the one you posted to the gcc-help list: enum class MyEnum { A = 1 }; struct MyClass { MyEnum Field1 : 3; }; Jason, the standard seems to say this should work, although I am rather surprised - is that intended?
What does 'rejects-valid' keywords mean? 18.11.2012 22:05 пользователь "redi at gcc dot gnu.org" < gcc-bugzilla@gcc.gnu.org> написал: > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51242 > > Jonathan Wakely <redi at gcc dot gnu.org> changed: > > What |Removed |Added > > ---------------------------------------------------------------------------- > Status|UNCONFIRMED |NEW > Last reconfirmed| |2012-11-18 > Ever Confirmed|0 |1 > > -- > Configure bugmail: http://gcc.gnu.org/bugzilla/userprefs.cgi?tab=email > ------- You are receiving this mail because: ------- > You reported the bug. >
(In reply to comment #2) > What does 'rejects-valid' keywords mean? It means that the compiler rejects valid code, see http://gcc.gnu.org/bugzilla/describekeywords.cgi
Sorry for stupid questions :) Is this bug planned to be fixed in future? Can I help in any way to do that? 2012/11/19 daniel.kruegler at googlemail dot com <gcc-bugzilla@gcc.gnu.org>: > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51242 > > --- Comment #3 from Daniel Krügler <daniel.kruegler at googlemail dot com> 2012-11-19 07:26:11 UTC --- > (In reply to comment #2) >> What does 'rejects-valid' keywords mean? > It means that the compiler rejects valid code, see > > http://gcc.gnu.org/bugzilla/describekeywords.cgi > > -- > Configure bugmail: http://gcc.gnu.org/bugzilla/userprefs.cgi?tab=email > ------- You are receiving this mail because: ------- > You reported the bug.
(In reply to comment #4) > Is this bug planned to be fixed in future? Yes, of course. It's a bug. > Can I help in any way to do that? Sure, you could look in gcc/cp/*.c for the message "bit-field .* with non-integral type" and see what conditions it depends on and why it disallows scoped enumeration types.
The check is for an unscoped enumeration type which does seem intentional. This change allows the example to compile: --- cp/decl2.c.orig 2012-11-19 11:50:28.842443803 +0000 +++ cp/decl2.c 2012-11-19 11:46:08.445472115 +0000 @@ -1026,7 +1026,7 @@ if (TREE_CODE (value) == VOID_TYPE) return void_type_node; - if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value)) + if (!INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value)) && (POINTER_TYPE_P (value) || !dependent_type_p (TREE_TYPE (value)))) { It emits a warning though: e.cc:5:19: warning: 'MyClass::Field1' is too small to hold all values of 'enum class MyEnum' [enabled by default]
OK, I will see this message soon. P.S. For now, I have to use Intel Compiller, which isn't good due limited platform support (x86 and amd64). ---Исходное сообщение--- От: "redi at gcc dot gnu.org" Отпр.: 19.11.2012, 15:47 Кому: volodya@netfolder.ru Тема: [Bug c++/51242] [C++11] Unable to use strongly typed enums as bit fields http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51242 --- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> 2012-11-19 11:47:20 UTC --- (In reply to comment #4) > Is this bug planned to be fixed in future? Yes, of course. It's a bug. > Can I help in any way to do that? Sure, you could look in gcc/cp/*.c for the message "bit-field .* with non-integral type" and see what conditions it depends on and why it disallows scoped enumeration types.
The warning noticed by Jon seems a latent issue unrelated to bitfields and due to the fact to for scoped enums, the underlying type, if not explicitly specified is if fixed to int type. Thus, in finish_enum_value_list, fixed_underlying_type_p is true and the code "restricting" ENUM_UNDERLYING_TYPE for the benefit of diagnostics doesn't run. It seems that it should run anyway, when the underlying type is fixed but implicitly so.
Or maybe it should *always* run, if the point is diagnostics: after all even if the type is fixed why not adding to its representation the information about the actual range of values of the enumerators?!?
For example, consider this variant of the PR53661 situation: enum class Code { SUCCESS = 0 }; Code a; short r[] = {a}; we currently produce a -Wnarrowing warning, which seems bogus to me, exactly because we don't realize that actually the only enumerator has value zero.
That narrowing warning seems right to me, the enum variable could have a value out of range of short: Code a = static_cast<Code>(SHRT_MAX+1);
The difference from PR 53661 is that the underlying type of a scoped enumeration is fixed, so its values are the values of (in this case) int. In PR 53661 the underlying type is not fixed.
But something still seems wrong to me. Why warning depending on whether 'class' is there for the following: enum /*class*/ Code { SUCCESS = 0 }; Code a; short r[] = {a};
Anyway, the latent issue is of course with fixed underlying types: if in that case we don't care about warning more, this issue is already fixed, very likely. Even better ;)
To be clear, for: enum class Code { SUCCESS = 0 }; Code a;// = static_cast<Code>(SHRT_MAX+1); short r[] = {a}; we *error* out anyway, isn't that we are only emitting a warning and only when we are assigning the SHRT_MAX + 1.
And to further clarify wrt your specific Comment 11, Jon, for: #include <limits.h> enum Code { SUCCESS = 0 }; Code a = static_cast<Code>(SHRT_MAX + 1); short r[] = {a}; we currently don't warn.
(In reply to comment #15) > we *error* out anyway, isn't that we are only emitting a warning and only when > we are assigning the SHRT_MAX + 1. But isn't the error because there's no implicit conversion from a scoped enunmeration type to short? That's just invalid. And my point is that the narrowing warning is correct, because 'a' is not a constant expression and its value could be out of the range [SHRT_MIN,SHRT_MAX]. (In reply to comment #16) > And to further clarify wrt your specific Comment 11, Jon, for: > > #include <limits.h> > > enum Code { > SUCCESS = 0 > }; > > Code a = static_cast<Code>(SHRT_MAX + 1); > > short r[] = {a}; > > we currently don't warn. Because the values of that unscoped enum type are [0,1] which always fit in short. With a scoped enumeration type the underlying type is fixed so the values of the enumeration type are the values of the underlying type which are [INT_MIN,INT_MAX]. But this seems unrelated to using scoped enums as bitfields anyway.
What can I say, if we are happy with these warnings when the underlying type is fixed, then I think your patch is all there is to this issue, just regression test it ;) It would be nice to double check that clang also warns, tough.
Clang doesn't warn for the code in comment 1
Well, then we should double check whether it warns at all when bitfields are not involved, because I don't see anything bitfield-specific about the warning. Maybe it just warns less for these narrowing issues with scoped and unscoped enums?
Uhm, actually, when the underlying type is unscoped and we already accept the code, we warn exactly in the same way. I'm not sure if this is already clear to everybody, definitely wasn't clear to me, sorry if I misled you Jon or somebody else into thinking that the possible issues having to do with -Wnarrowing were important for this issue, I understand now they are not: enum MyEnum { A1 = 1, A2 = 2 }; struct MyClass { MyEnum Field1 : 1; }; Thus, it really seems the fix for this issue boils down to loosening the check in grokbitfield and that's it.
I mean, with the grokbitfield tweak we obtain a behavior for Comment #1 which in terms of warnings it's just a variant of Comment #13: if we already decided that it's fine to warn when the underlying type is fixed for Comment #13, we have in my opinion to consistently warn for Comment #1.
Patchlet in Comment #6 passes testing for me. As I tried clumsily to explain, I don't think it's consistent to avoid the warning for Comment #1 if we warn for Comment #13 scoped, but it's also annoying that the "too small to hold all values" warning it's enable by default, thus can't be suppresed: maybe we could give it a name (if we don't want to re-open the discussion about -Wnarrowing and the range of the underlying type when the type is fixed ;)
I think naming the warning would make sense, so it can be disabled by people who want to use scoped enums with bit-fields
Author: paolo Date: Sat Feb 16 01:07:11 2013 New Revision: 196100 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=196100 Log: /cp 2013-02-15 Jonathan Wakely <jwakely.gcc@gmail.com> Paolo Carlini <paolo.carlini@oracle.com> PR c++/51242 * decl2.c (grokbitfield): Allow scoped enumeration types. /testsuite 2013-02-15 Jonathan Wakely <jwakely.gcc@gmail.com> Paolo Carlini <paolo.carlini@oracle.com> PR c++/51242 * g++.dg/cpp0x/enum23.C: New. Added: trunk/gcc/testsuite/g++.dg/cpp0x/enum23.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/decl2.c trunk/gcc/testsuite/ChangeLog
Note: I'm keeping this open because we may want to do something about the warning: http://gcc.gnu.org/ml/gcc-patches/2013-02/msg00786.html
We got bit by this warning recently. We compile with -Werror and, without an option to suppress warnings in the following code, gcc rejects it. We think this code should be accepted without a warning given the constant expressions involved. Clang does not issue a warning for this code. However, if an assignment to the bit-field from a literal '2' (cast to E) is added, then Clang warns on the assignment itself (as opposed to on the bit-field declaration). This seems like a more useful approach. $ cat t.cpp enum E : unsigned char { e0 = 0, e1 = 1 }; struct S { E e : 1; }; void f(S s) { s.e = e0; s.e = e1; s.e = (E)0; s.e = (E)1; }; $ g++ --version g++ (GCC) 6.1.1 20160531 ... $ g++ -c -std=c++11 -Werror t.cpp t.cpp:6:11: error: ‘S::e’ is too small to hold all values of ‘enum E’ [-Werror] E e : 1; ^ cc1plus: all warnings being treated as errors
I contribute to Chromium and have also hit problems such as Comment 27. I'm in the process of submitting a patch to Clang (https://reviews.llvm.org/D24289) that warns when enums used in bitfields are not given an unsigned underlying type, since MSVC defaults to signed underlying types and this gives inconsistencies when reading/writing the bitfield in multi-platform code. With the patch, the following code: enum Foo { A, B }; struct Bar { Foo x : 1 }; will give the following warning with Clang: "enums in the Microsoft ABI are signed integers by default; consider giving the enum Foo an unsigned underlying type to make this code portable" But then if it's changed to enum Foo : unsigned { A, B }; struct Bar { Foo x : 1 }; GCC will give the warning: "'Bar::x' is too small to hold all values of 'enum Foo'" The C++ standard says: 9.6.4 says: If the value of an enumerator is stored into a bit-field of the same enumeration type and the number of bits in the bit-field is large enough to hold all the values of that enumeration type (7.2), the original enumerator value and the value of the bit-field shall compare equal. You can disregard whether the underlying type is fixed or not. So, GCC should not give a warning unless a bitfield containing Foo really is too small to hold a given value of Foo, warning on the assignment makes sense.
(In reply to Sasha B from comment #28) > You can disregard whether the underlying type is fixed or not. So, GCC > should not give a warning unless a bitfield containing Foo really is too > small to hold a given value of Foo, warning on the assignment makes sense. I agree that we could warn on assignment instead. If the values assigned to the bitfield are constant and known to fit, there's no need to warn. See PR 61414 for the same warning. I don't know if we need to keep both bugs open.
(In reply to Jonathan Wakely from comment #29) > (In reply to Sasha B from comment #28) > > You can disregard whether the underlying type is fixed or not. So, GCC > > should not give a warning unless a bitfield containing Foo really is too > > small to hold a given value of Foo, warning on the assignment makes sense. > > I agree that we could warn on assignment instead. If the values assigned to > the bitfield are constant and known to fit, there's no need to warn. See PR > 61414 for the same warning. I don't know if we need to keep both bugs open. Yes I agree that this warning has no sense if the constant don't reach the maximum bits used in bitfield. Instead of solution where warning is possible to disable with switch will be better to test if maximum constant in enum will fit into bitfield.
Apparently this was fixed in 9.3? enum class Color { Red, Green, Blue }; struct X { Color c : 2; }; auto x = X{.c=Color::Red}; warns on 9.2, but not anymore on 9.3 or 10.
(In reply to Barry Revzin from comment #31) > warns on 9.2, but not anymore on 9.3 or 10. Changed by r278736 for PR c++/61414 In comment 26 Paolo said this was kept open because of the warning that Jakub fixed, so I'm closing this.