GCC 抑制警告"too small to hold all values of"

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

本文关键字:hold all values of to too 警告 GCC small      更新时间:2023-10-16

我需要使用作用域枚举,以便我可以将它们作为特定类型传递给我们的序列化器。我已经为 Enum1 的枚举成员给出了显式整数值。

我已经将两个与上述描述匹配的作用域枚举放入一个位域中,因此

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;
}

现在,无论我在哪里使用 Example 类型,我都会收到警告"'example::value1' 太小,无法容纳 'Enum1' 的所有值",同样适用于 Enum2 .请注意,我们定义的值并非如此,我们根本不关心这些值之外的值。

这在我们的构建过程中是一个相当严重的分心 - 项目庞大而复杂,我们不想扫描其中的许多警告(而且有很多)。

我寻找了一个GCC(G ++)标志来禁用特定的警告。有没有我可以在命令行上传递的?理想情况下,如果可能,我会使用警告杂注在本地禁用它。

在这一点上,更改代码结构的余地很小,但我们确实可以使用删除这些虚假警告。

编辑:添加了标识符已更改的作用域枚举。

问题是作用域枚举始终具有完整的基础类型。默认情况下,它是int的,但您可以将其更改为任何其他整数类型,例如 unsigned char

遗憾的是,您无法将基础类型更改为位字段,因为它们不是真正的C++类型。

您可以尝试禁用警告,但快速浏览 G++ 代码会显示以下行 ( 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);

这里的关键是调用warning_at(...)而不是warning(OPT_to_disable_the_warning, ...)。因此,目前没有禁用它的选项。除了自己重新编译编译器!

对于它的价值 CLang++-3.7.1 没有警告它。

我记得,具有声明底层类型的枚举可以保存该类型的任何值,而不管定义了什么枚举常量。 既然你可以说

val= enum2{148}

并期望它正常工作,在这种情况下,警告似乎是正确的。 您没有声明基类型,从历史上看,这意味着枚举仅保证足够大,以容纳最低到最高枚举常量给出的值范围。 所以我预计这里没有任何警告。 也许新enum class也期望一个完整的范围,即使基础类型是自动确定的(或者编译器认为是这样)? 您可以尝试使用纯旧语法枚举,看看它是否有什么不同。

发出此警告是一个错误,因为所有声明的枚举器(值)实际上都可以由位字段保存。

与传统枚举一样,作用域枚举类型的变量仍然可以保存其基础类型的任何值,即使是与声明的枚举器不对应的值。

但是,像这样警告

warning: 'some bitfield field' is too small to hold all values of 'enum class FOO'

是毫无意义的,因为分配一个太大的值,如

Example x;
x.value1 = Enum1(8);

已生成-Woverflow警告。

<小时 />

因此,GCC 在版本 9.3 中修复了此警告。

FWIW,叮当从来没有警告过。

<小时 />

IOW,要在 GCC 中禁止显示此警告,您必须升级到 GCC 版本 9.3 或更高版本。

对于像我这样从搜索中最终来到这里的其他人:

此问题仅适用于 C++11 作用域枚举。如果您需要位域枚举,没有显式存储大小的旧式枚举可以正常工作:

enum Enum1 {
    Enum1_value1 = 0x0,
    Enum1_value2 = 0x1,
    Enum1_value3 = 0x2
};
enum Enum2 {
    Enum2_value1 = 0x0,
    Enum2_value2,
    Enum2_value3,
 // ...
    Enum2_value14
};
struct Example {
    Enum1 value1 : 2;
    Enum2 value2 : 6;
}