Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gcc suppress warning "too small to hold all values of"

I need to use scoped enums so that I can pass them as specific types to our serialiser. I have given explicit integer values for the enum members of Enum1.

I have put two scoped enums matching the description above into a bitfield thus

enum class Enum1 {
    value1 = 0x0,
    value2 = 0x1,
    value3 = 0x2
};
enum class Enum2 {
    value1 = 0x0,
    value2,
    value3,
 // ...
    value14
};

struct Example {
    Enum1 value1 : 2;
    Enum2 value2 : 6;
}

Now wherever I use the Example type, I get the warning "'Example::value1' is too small to hold all values of 'Enum1'", and similarly for Enum2. Note that this is not the case for the values we have defined and we are not concerned at all with values outside of these.

This is quite a serious distraction in our build process - the project is large and complex and we don't want to have to scan through many of these warnings (and there are many).

I had a look for a GCC (G++) flag to disable the specific warning. Is there one that I can pass on the command line? Ideally, I would use the warning pragma to disable it locally, if possible.

There is little scope for changing the code structure at this point, but we could really use these spurious warnings removed.

Edit: Added scoped enums with identifiers changed.

like image 500
jsren Avatar asked Mar 15 '16 07:03

jsren


2 Answers

The problem is that an scoped enum always has an integral underlying type. By default, it is int but you can change it to any other integral type, such as unsigned char.

Unfortunately you cannot change the underlying type to a bit-field, as they are not real C++ types.

You could try disabling the warning, but a quick skim through the G++ code reveals these lines (gcc/cp/class.c:3468):

  else if (TREE_CODE (type) == ENUMERAL_TYPE
           && (0 > (compare_tree_int
                    (w, TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type))))))
    warning_at (DECL_SOURCE_LOCATION (field), 0,
                "%qD is too small to hold all values of %q#T",
                field, type);

The key here is the call to warning_at(...) instead of warning(OPT_to_disable_the_warning, ...). So currently there is no option to disable it. Except recompiling the compiler yourself!

For what it is worth CLang++-3.7.1 does not warn about it.

like image 156
rodrigo Avatar answered Oct 28 '22 20:10

rodrigo


As I recall, an enum with a declared underlying type can hold any value of that type, regardless of what enumeration constants are defined. Since you can say

val= enum2{148}

and expect it to work properly, the warning seems correct for that case. You are not declaring a base type, and historically this means that the enum is only guaranteed to be big enough to hold the range of values given by the lowest through highest enumeration constant. So I would expect no warning here. Maybe the new enum class also expects a full range even though the underlying type was automatically determined (or the compiler thinks it does)? You might try using a pure old-syntax enum and see if that works any differently.

like image 3
JDługosz Avatar answered Oct 28 '22 18:10

JDługosz