启用彻底和详细的g ++警告的标志


122

通常在C下gcc,我将从以下警告标志集开始(从多个来源痛苦地组合起来):

-Wall -Wextra -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wbad-function-cast \
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef \
-Wnested-externs -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-parameter \
-Wfloat-equal -pedantic -ansi

我将使用这组警告构建(至少是我的调试版本),并修复所有可能的内容(通常是所有内容),然后仅在不相关或不可修复的标记时才将其删除(几乎永远不会这样)。有时,-Werror如果在编译时必须离开,我也会添加。

我只是在学习C ++(是的,我落后时代15年),我想从右脚开始。

我的问题是:是否有人在下面为C ++预编译了一组类似的完整警告标志g++?(我知道其中许多都一样。)


69
gcc需要的(因为已经决定公然撒谎-Wall)是一个-Wbloody_everything标记:-)
paxdiablo 2011年

您可以将问题标记为重复,但也可以将最后一次编辑作为答案,因为您实际上已经回答了问题。然后,我很乐意
投票赞成

4
OP和@paxdiablo:GCC一直拒绝这种事情,但是可以通过Clang在Clang中使用-Weverything。我读过,即使Clang ++开发人员也有点担心用户将其打开。显然,它仅用于内部开发。不过,这没有任何意义,因为打开电源-Weverything可能是发现您以前不知道的潜在有用警告的最佳方法。
Kyle Strand

1
OP和@paxdiablo现在,有一种方法可以找出给定GCC版本的完整警告列表:github.com/barro/compiler-warnings
Kyle Strand,

Answers:


137

我仔细研究了一下,发现应该包含最大警告级别的最小包含集。然后,我从该列表中删除了一些警告,这些警告我认为实际上并没有表明正在发生不良情况,或者有太多误报无法在实际版本中使用。我评论了为什么我排除的每个人都被排除在外。这是我建议的最后一组警告:

-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused

存在可疑的警告:

  • -Wno-unused之所以加入,是因为我经常有一些变量,这些变量我以后会用到,但是还没有编写功能。删除有关该内容的警告,使我能够以自己偏爱的风格编写内容,这种风格有时会延迟事物的实现。每隔一段时间关闭一次电源很有用,以确保没有任何东西滑出裂缝。

  • -Wdisabled-optimization似乎是强大的用户偏好设置。我只是将此代码添加到了我的版本中(出于明显的原因,仅用于优化的版本),它并没有显示任何内容,因此,至少对于我的编码方式而言,它似乎并不是特别健谈的警告。我包括了它(即使触发此警告的代码不一定是错误的),因为我相信使用我的工具而不是反对它们。如果gcc告诉我它无法按照我编写代码的方式优化代码,那么我应该考虑重写它。我怀疑触发此警告的代码可能会受益于更高的模块化程度,因此,尽管该代码在技术上并没有错(可能),但从样式上看却可能是错的。

  • -Wfloat-equal警告进行安全相等性比较(尤其是与非计算值-1进行比较)。我使用此代码的示例中有一个向量float。我经历了这个向量,有些元素我还无法评估它们应该是什么,因此我将它们设置为-1.0f(因为我的问题仅使用正数,因此-1在域外)。稍后,我将更新-1.0f值。它不容易使自己适合于其他操作方法。我怀疑大多数人都没有这个问题,并且比较浮点数的确切数字可能是一个错误,因此我将其包含在默认列表中。

  • -Wold-style-cast我正在使用的库代码中有很多误报。特别是,网络中使用的htonl函数系列,以及我正在使用的Rijndael(AES)加密实现,都警告了我。我打算将它们都替换掉,但是我不确定代码中是否还有其他东西要抱怨。不过,大多数用户可能应该默认启用此功能。

  • -Wsign-conversion是一个艰难的人(几乎没有上榜)。在我的代码中将其打开会产生大量警告(超过100条)。几乎所有人都是无辜的。但是,我不确定在任何不确定的地方都使用有符号整数,尽管对于我特定的问题域,由于我做大量的整数除法操作,使用无符号值通常会稍微提高效率。我之所以牺牲效率是因为我担心会意外地将有符号整数提升为无符号整数然后进行除法(这是不安全的,与加法,减法和乘法不同)。启用此警告后,我可以安全地将大多数变量更改为无符号类型,并在其他位置添加一些强制类型转换。当前使用起来有点困难,因为警告并不那么聪明。例如,如果您这样做unsigned short + (integral constant expression),该结果隐式提升为int。如果您将该值分配给unsignedunsigned short,它会警告您潜在的标志问题 ,即使它是安全的。对于几乎所有用户,这绝对是最可选的警告。

  • -Wsign-promo:参见-Wsign-conversion

  • -Wswitch-default似乎毫无意义(如果您已经明确列举了所有可能性,则不一定总是需要默认情况)。但是,打开此警告可以强制执行可能是个好主意。如果您明确想忽略除所列可能性之外的所有内容(但其他数字也是可能的),请输入default: break;使其明确。如果您明确列举所有可能性,那么打开此警告将有助于确保您放入诸如assert(false)之类的内容,以确保您实际上涵盖了所有可能的选项。它使您可以明确指出问题所在的领域,并以编程方式强制执行该问题。但是,您必须小心在所有位置都使用assert(false)。这比对默认情况不执行任何操作要好,但是与assert一样,它在发行版本中不起作用。换句话说,您不能依靠它来验证您从没有绝对控制权的网络连接或数据库获得的号码。异常或提早返回是处理该问题的最佳方法(但仍然需要您使用默认情况!)。

  • -Werror对我来说是重要的 在具有多个目标的多线程构建中编译大量代码时,很容易出现警告漏失的情况。将警告变成错误可以确保我注意到它们。

然后,有一组警告未包含在上面的列表中,因为我认为它们没有用。这些是警告和我对为什么不将它们包括在默认列表中的评论:

缺少警告:

  • -Wabi不需要,因为我没有合并来自不同编译器的二进制文件。无论如何,我都尝试使用它进行编译,并且它没有触发,因此它似乎并不需要冗长。

  • -Waggregate-return我认为这不是错误。例如,当在类的向量上使用基于范围的for循环时,它将触发。返回值优化应解决此问题的任何负面影响。

  • -Wconversion在此代码上触发:short n = 0; n += 2;隐式转换为int时,如果将其转换回其目标类型,则会引发警告。

  • -Weffc++如果未在初始化列表中初始化所有数据成员,则包括警告。在许多情况下,我故意不执行此操作,因此这组警告过于混乱而无用。但是,每隔一段时间打开一次并扫描其他警告(例如基类的非虚拟析构函数)会很有帮助。作为警告集合(如-Wall),而不是单独的单个警告,这将更为有用。

  • -Winline之所以缺席,是因为我没有将inline关键字用于优化目的,只是为了在标头中内联定义函数。我不在乎优化器是否真正内联它。如果无法内联在类主体中声明的函数(例如,空的虚拟析构函数),则此警告也会抱怨。

  • -Winvalid-pch 丢失了,因为我不使用预编译的头文件。

  • -Wmissing-format-attribute不使用,因为我不使用gnu扩展。与-Wsuggest-attribute其他几个相同

  • 可能值得注意的是-Wno-long-long,它是我不需要的。我使用-std=c++0x-std=c++11在GCC 4.7中)进行编译,其中包括long long整数类型。那些坚持使用C ++ 98 / C ++ 03的用户可以考虑将其排除在警告列表之外。

  • -Wnormalized=nfc 已经是默认选项,并且看起来是最好的。

  • -Wpadded有时会打开来优化类的布局,但由于并非所有类都具有足够的元素以消除结尾的填充,因此未启用它。从理论上讲,我可以为“免费”获得一些额外的变量,但是不值得为此付出额外的努力(如果我的班级大小发生变化,删除那些以前免费的变量并不容易)。

  • -Wstack-protector 不使用,因为我不使用 -fstack-protector

  • -Wstrict-aliasing=3由开启-Wall并且是最准确的,但看起来第1级和第2级会发出更多警告。从理论上讲,较低的级别是“更强”的警告,但这是以更多的误报为代价的。我自己的测试代码可以在所有3个级别下干净地编译。

  • -Wswitch-enum不是我想要的行为。我不想显式地处理每个switch语句。如果该语言具有某种机制可以在指定的switch语句上激活它(以确保将来需要对枚举进行的更改可以在需要处理的所有地方进行处理),则将很有用,但是对于“全有或全无”设置而言,这是过头的。

  • -Wunsafe-loop-optimizations导致太多虚假警告。定期应用此方法并手动验证结果可能会很有用。例如,当我遍历向量中的所有元素以向它们应用一组功能时(使用基于范围的for循环),它在我的代码中生成了此警告。对于const std :: string的const数组的构造函数(这在用户代码中没有循环)也警告。

  • -Wzero-as-null-pointer-constant并且-Wuseless-cast是仅限GCC-4.7的警告,我将在过渡到GCC 4.7时添加这些警告。

由于这项研究,我已经在gcc上提交了一些错误报告/增强功能请求,因此希望我最终能够将更多的警告从“不包括”列表添加到“包含”列表中。该列表包括该线程中提到的所有警告(另外,我认为还有一些警告)。我没有提到的另一个警告中包含了本文中未明确提及的许多警告。如果有人发现任何被本帖子完全排除的警告,请告诉我。

编辑:好像我错过了几个(现在我已经添加了)。实际上,http://gcc.gnu.org上有第二个页面,该页面非常隐蔽。常规警告选项C ++选项(向下滚动至警告底部)


我最近根据研究结果针对此答案提交了增强请求:gcc.gnu.org/bugzilla/show_bug.cgi?id=53313。通过创建警告级别,可以大大简化警告情况。在我的建议中,我建议的警告集大约为-W4,另外还建议创建-Winf,这将意味着-这一次
大卫·斯通

可能会导致-Wpapped的一部分的增强请求被添加到推荐列表中:gcc.gnu.org/bugzilla/show_bug.cgi?
David Stone

可能导致-Weffc ++部分被添加到推荐列表的增强请求:gcc.gnu.org/bugzilla/show_bug.cgi?
David Stone

1
@Predelnik:比这要复杂得多。-Wswitch-enum如果未在开关中显式处理每个枚举值,则发出警告,并且default不算作显式。另一方面,即使您已明确涵盖所有可能的值,-Wswitch-default如果您的开关没有default大小写,也会发出警告。
大卫·斯通

2
顺便说一句-使用-isystem而不是-I在您的“旧库代码”
上来

39

D'oh,我的所有原始搜索都出现了99%的帖子(关于如何抑制警告)(足够吓人),但是我碰到了这个注释,它带有一组可爱的标志(有些不太相关):

交叉检查:

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

-g -O -Wall -Weffc++ -pedantic  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline \
-Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings

因此,我认为这是一个很好的起点。没意识到这是一个骗子,但至少它被深深地埋了。:-)


1
也许吧,但是这似乎在版本之间有所改变,并且可能会在太阳光斑和RMS的短暂影响下发生变化,因此过分明朗可能不会造成伤害。无论如何,这是一个很好的起点。
Sdaz MacSkibbons 2011年

3
从4.5.2的c-opts.c / opts.c快速grep(针对“ case OPT_W”)中,您会丢失:严格的溢出,undef,严格的nul定点,规范化,multichar,隐式函数声明,不建议使用的endif标签, comment s,重新定义了内置宏,大于,大于eq,abi。疯狂的是,没有命令行选项可以列出它们。
Tony Delroy,

3
我认为这比-Wall人们期望的要疯狂得多。但是,谢谢您,其中一些看起来非常有用!
Sdaz MacSkibbons 2011年

1
禁用警告很重要。毕竟,它们是“警告”。另一种情况是,当您启用一个可启用多个警告的标志时,您希望对此有所选择。
陶Szelei

1
您如何使用-Waggregate-return?这使我每次使用的警告begin/end()
Flamefire

12

其中一些已经包含在-Wall或中-Wextra

C的良好基础设置是:

-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror

对于C ++

-ansi -pedantic -Wall -Wextra -Weffc++

-Werror由于-Weffc++存在一些烦恼,因此跳过了C ++ )


10
-Werror可以针对特定类型的警告禁用,例如:-Werror -Weffc ++ -Wno-error = effc ++
Robert Hensing

2
ansi:在C模式下,它等效于-std=c89。在C ++模式下,它等效于-std=c++98。即,如果您指定其他名称std,请不要使用ansi
Sean Breckenridge

2

尝试

export CFLAGS="`gcc --help=warnings | grep '\-W' | awk '{print $1 \" \"}' |
sort | uniq` -pedantic -fdiagnostics-show-option -Werror"

这是一个快速而肮脏的开始,肯定需要进行一些调整。一方面,即使您使用适合您的语言的名称来调用编译器(例如,g++对于C ++),您也会收到不适用于该语言的警告(并且编译器会举手并拒绝继续操作,直到您删除警告)。

另一件事是我添加的-Werror,因为如果您不修正警告,为什么还要关心将它们打开?您也可以从列表中删除警告。(例如,我几乎从不使用-Waggregate-returnC ++。)

如果没有其他与性能相关的选项(-Wstack-protector),某些警告将无法执行任何操作。-fdiagnostics-show-option和GCC手册是您的朋友。

顺便说一句,有些警告是互斥的。特别是-Wtraditional-Wold-style-definition一起使用时-Werror,将无法编译。


0

在我的Clion的CmakeLists.txt中

cmake_minimum_required(VERSION 3.13)
project(cpp17)

set(CMAKE_CXX_STANDARD 17)

set(GCC_COVERAGE_COMPILE_FLAGS "-std=c++17 -Wall -Weffc++ -Wno-error=effc++ -pedantic \
 -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-newline-eof  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline -Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings")


set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )

add_executable(cpp17 main.cpp)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.