如何打开(字面上)所有GCC的警告?

时间:2012-07-30 02:39:09

标签: c++ gcc warnings compiler-warnings gcc-warning

我想启用 - 字面上 - 全部 GCC的警告。 (你认为这很容易......)

  • 你认为-Wall可能会成功,但不是!仍然需要-Wextra

  • 你认为-Wextra可能会成功,但不是!并非列出here列出的所有警告(例如,-Wshadow)都是由此启用的。我仍然不知道这份清单是否全面。

我如何告诉GCC启用(不是,不是,或者是!)所有它有什么警告?

7 个答案:

答案 0 :(得分:111)

你做不到。

GCC 4.4.0手册仅适用于该版本,但它列出了4.4.0的所有可能警告。它们并不是您链接到的页面上的所有内容,例如,某些特定于语言的选项位于C ++选项或Obj-C选项的页面上。为了找到它们,你最好不要看Options Summary

启用所有内容将包含-Wdouble-promotion,它仅与具有32位单精度浮点单元的CPU相关,该单元在硬件中实现float,但模拟软件double。以double进行计算将使用软件仿真并且速度较慢。这与某些嵌入式CPU相关,但与具有64位浮点硬件支持的现代桌面CPU完全无关。

另一个通常不常用的警告是-Wtraditional,它警告传统C中具有不同含义(或不起作用)的完美良好的代码,例如: "string " "concatenation"或ISO C函数定义!你真的关心与30岁编译器的兼容性吗?你真的想要写一个int inc(int i) { return i+1; }的警告吗?

我认为-Weffc++过于嘈杂而无用,它基于过时的第一版 Effective C ++ ,并警告有关C ++完全有效的构造(并且指南已更改)在本书的后续版本中。)我不想被警告我没有在我的构造函数中初始化std::string成员;它有一个默认的构造函数,它完全符合我的要求,为什么要写m_str()来调用呢? -Weffc++警告对于编译器来说太难以准确检测(给出错误否定),而那些无效的警告(如明确初始化所有成员)只会产生太多噪音,给出错误阳性。

Luc Danton提供-Waggregate-return来自-Wall -Wextra的{​​{3}}无用警告,几乎可以肯定对C ++代码没有意义。

即。你真的不想要所有警告,你只是认为你这样做。

阅读手册,阅读相关内容,确定您可能要启用哪些内容,然后尝试使用它们。无论如何,阅读编译器的手册是一件好事 TM ,采取捷径并启用你不理解的警告并不是一个好主意,特别是如果要避免使用RTFM。

great example

Anyone who just turns on everything is probably either doing so because they're clueless because or a pointy-haired boss said "no warnings."

修改:另请参阅作为WONTFIX关闭的Some warnings are important, and some aren't. You have to be discriminating or you mess up your program. Consider, for instance, -Wdouble-promotion. If you're working on an embedded system you might want this; if you're working on a desktop system you probably don't. And do you want -Wtraditional? I doubt it.

编辑2:以回应DevSolar关于makefile需要根据编译器版本使用不同警告的抱怨,如果compiler_name := $(notdir $(CC)) ifeq ($(compiler_name),gcc) compiler_version := $(basename $(shell $(CC) -dumpversion)) endif ifeq ($(compile_name),clang) compiler_version := $(shell $(CC) --version | awk 'NR==1{print $$3}') endif # ... wflags.gcc.base := -Wall -Wextra wflags.gcc.4.7 := -Wzero-as-null-pointer-constant wflags.gcc.4.8 := $(wflags.gcc.4.7) wflags.clang.base := -Wall -Wextra wflags.clang.3.2 := -Weverything CFLAGS += $(wflags.$(compiler_name).base) $(wflags.$(compiler_name).$(compiler_version)) 不适合那么使用编译器特定的并不困难特定版本的CFLAGS:

{{1}}

答案 1 :(得分:52)

我同意之前的答案,即启用字面上的所有警告可能没有帮助,但是GCC确实提供了一种相当方便的方法来实现这一点。命令

gcc -Q --help=warning

提供所有支持的警告选项的列表,以及有关它们是否处于活动状态的信息。顺便说一下,这可以用于找出(未)启用哪些选项。 -Wall-Wextra

gcc -Wall -Wextra -Q --help=warning

要启用所有警告,您可以使用一些正则表达式来提取命令行参数

gcc -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n'

对于我目前的GCC,这给出了:

  <-Wabi -Wabi-tag -Wadgn -Waggregate-return -Waggressive-loop-optimizations -Waliasing -Walign-commons -Wampersand -Warray-bounds -Warray-temporaries -Wassign-intercept -Wattributes -Wbad-function-cast- Wbool-compare -Wbuiltin-macro-redefined -Wc ++ - compat -Wc ++ 0x-compat -Wc ++ 14-compat -Wc-binding-type -Wc90-c99-compat -Wc99-c11-compat -Wcast-align - Wcast-qual -Wchar-subscripts -Wcharacter-truncation -Wchkp -Wclobbered -Wcomment -Wcompare-reals -Wconditionally-supported -Wconversion -Wconversion-extra -Wconversion-null -Wcoverage-mismatch -Wcpp -Wctor-dtor-privacy -Wdate- time -Wdeclaration-after-statement -Wdelete-incomplete -Wdelete-non-virtual-dtor -Wdeprecated -Wdeprecated-declarations -Wignedated-init -Wdisabled-optimization -Wdiscarded-array-qualifiers -Wdiscarded-qualifiers -Wdiv-by-zero - Wdouble-promotion -Weffc ++ -Wempty-body -Wendif-labels -Wenum-compare -Wextra -Wfloat-equal -Wformat-contains-nul -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-signednes s -Wformat-y2k -Wformat-zero-length -Wfree-nonheap-object -Wfunction-elimination -Wignored-qualifiers -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimplicit-interface -Wimplicit-procedure -Wincompatible-pointer- types -Winherited-variadic-ctor -Winit-self -Winline -Wint-conversion -Wint-to-pointer-cast -Wintrinsic-shadow -Wintrinsics-std -Winvalid-memory-model -Winvalid-offsetof -Winvalid-pch -Wjump- misses-init -Wline-truncation -Wliteral-suffix -Wlogical-not-parentheses -Wlogical-op -Wlong-long -Wmain -Wmaybe-uninitialized -Wmemset-transposed-args -Wmissing-braces -Wmissing-declarations -Wmissing-field- initializers -Wmissing-include-dirs -Wmissing-parameter-type -Wmissing-prototypes -Wmultichar -Wnarrowing -Wnested-externs -Wnoexcept -Wnon-template-friend -Wnon-virtual-dtor -Wnonnull -Wodr -Wold-style-cast - Wold-style-declaration -Wold-style-definition -Wopenmp-simd -Woverflow -Woverlength-strings -Woverloaded-virtual -Woverride-init -Wpacked -Wpacked-bitfield-compat -Wpa dded -Wparentheses -Wpedantic -Wpmf-conversions -Wpointer-arith -Wpointer-sign -Wpointer-to-int-cast -Wpragmas -Wproperty-assign-default -Wprotocol -Wreal-q-constant -Wrealloc-lhs -Wallalloc-lhs- all -Wredundant-decls -Wreorder -Wreturn-local-addr -Wreturn-type -Wselector -Wsequence-point -Wshadow -Wshadow-ivar -Wshift-count-negative -Wshift-count-overflow -Wsign-compare -Wsign-promo - Wsized-deallocation -Wsizeof-array-argument -Wsizeof-pointer-memaccess -Wstack-protector -Wstrict-null-sentinel -Wstrict-prototypes -Wstrict-selector-match -Wsuggest-attribute = const -Wsuggest-attribute = format -Wsuggest- attribute = noreturn -Wsuggest-attribute = pure -Wsuggest-final-methods -Wsuggest-final-types -Wsuggest-override -Wsurprising -Wswitch -Wswitch-bool -Wswitch-default -Wswitch-enum -Wsync-nand -Wsynth -Wsystem- headers -Wtabs -Wtarget-lifetime -Wditional -Wditional-conversion -Wtrampolines -Wtrigraphs -Wtype-limits -Wundeclared-selector -Wundef -Wunderflow -Wuninitialized -Wunknown-pragmas -W unsafe-loop-optimizations -Wunnsixed-float-constants -Wunused -Wunused-but-set-parameter -Wunused-but-set-variable -Wunused-dummy-argument -Wunused-function -Wunused-label -Wunused-local-typedefs - Wunused-macros -Wunused-parameter -Wunused-result -Wunused-value -Wunused-variable -Wuse-without-only -Wuseless-cast -Wvarargs -Wvariadic-macros -Wvector-operation-performance -Wvirtual-move-assign -Wvla - Wvolatile-register-var -Wwrite-strings -Wzero-as-null-pointer-constant -Wzerotrip -frequire-return-statement

现在可用于呼叫GCC,即

gcc $(gcc -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n')

但请注意,由于某些警告选项仅适用于某些语言(例如C++),因此会产生警告。通过使用更多正则表达式仅包含当前语言允许的选项或在调用结束时添加适当的-Wno-whatever,可以避免这些问题。

答案 2 :(得分:14)

在启用所有警告的情况下编程是完全不可能的(除非你要忽略它们,但那么,为什么要打扰?)。例如,假设您使用以下一组标志:-Wstrict-prototypes -Wtraditional

即使启用了两个警告,以下程序也会抱怨。

/tmp $ cat main.c 
int main(int argc, char **argv) {
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c: In function ‘main’:
main.c:1:5: warning: traditional C rejects ISO C style function definitions [-Wtraditional]
 int main(int argc, char **argv) {
     ^

你可能会认为“好吧,我将使用旧式原型”。不,这不行。

/tmp $ cat main.c 
int main(argc, argv)
    int argc;
    char **argv;
{
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c:1:5: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
 int main(argc, argv)
     ^

不,不指定任何原型也是错误的,因为编译器也会抱怨。

/tmp $ cat main.c 
int main() {
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c:1:5: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
 int main() {
     ^

如果在程序中定义任何函数,则不能使用所有标志,因为编译器会抱怨任何可以想象的函数定义。

对于C ++,这是可能的(-Wtraditional标志不存在),并且可以编译非常简单的程序。要启用所有警告,请使用以下警告列表(可能是某些警告重复,因为我没有费心过滤-Wall启用的警告)。

-Wabi -Wctor-dtor-privacy -Wnon-virtual-dtor -Wreorder -Weffc++ -Wstrict-null-sentinel -Wno-non-template-friend -Wold-style-cast -Woverloaded-virtual -Wno-pmf-conversions -Wsign-promo -Wextra -Wall -Waddress -Waggregate-return -Warray-bounds -Wno-attributes -Wno-builtin-macro-redefined -Wc++0x-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wclobbered -Wcomment -Wconversion -Wcoverage-mismatch -Wno-deprecated -Wno-deprecated-declarations -Wdisabled-optimization -Wno-div-by-zero -Wempty-body -Wenum-compare -Wno-endif-labels -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wignored-qualifiers -Winit-self -Winline -Wno-int-to-pointer-cast -Wno-invalid-offsetof -Winvalid-pch -Wunsafe-loop-optimizations -Wlogical-op -Wlong-long -Wmain -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wno-mudflap -Wno-multichar -Wnonnull -Wno-overflow -Woverlength-strings -Wpacked -Wpacked-bitfield-compat -Wpadded -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wsign-conversion -Wstack-protector -Wstrict-aliasing=1 -Wstrict-overflow=5 -Wswitch -Wswitch-default -Wswitch-enum -Wsync-nand -Wsystem-headers -Wtrigraphs -Wtype-limits -Wundef -Wuninitialized -Wunknown-pragmas -Wno-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvla -Wvolatile-register-var -Wwrite-strings

答案 3 :(得分:5)

有人创建了一套工具,用于确定给定GCC或Clang版本的完整警告集。

对于GCC,从此工具为您的编译器版本提供的完整警告列表中复制似乎是唯一的方式,以确保所有警告都已打开,因为(与Clang不同)GCC不提供-Weverything

该工具似乎解析了GCC源代码中的实际c.opt文件,因此其结果应该是确定的。

存储库还包含文本文件,其中包含为大多数GCC和Clang版本生成的警告列表(目前为Clang 3.2至3.7和GCC 3.4至5.3)。

https://github.com/barro/compiler-warnings

答案 4 :(得分:5)

Gcc 4.3+现在有-Q --help =警告,你甚至可以指定--help = warnings,C来打印出与C相关的警告。

我刚刚写了一个m4模块来利用这个(也支持clang的-Weverything),见wget_manywarnings.m4

如何使用它非常简单,基本上模块会打开每个警告标志。你根据需要删除警告 - 有些真的非常冗长。 示例:configure.ac

如果你不使用autotools,你会发现代码打开m4模块中所有禁用的警告,这基本上是通过awk传输的gcc:

flags="-Wall -Wextra -Wformat=2 "$(gcc -Wall -Wextra -Wformat=2 -Q --help=warning,C|awk '{ if (($2 == "[disabled]" || $2 == "") && $1!~/=/ && $1~/^-W/&& $1!="-Wall") print $1 }'

答案 5 :(得分:3)

来自this page

  

请注意-Wall不暗示某些警告标志。他们中有一些   警告用户通常不考虑的结构   有问题,但偶尔你可能想检查一下;   其他人警告有必要或难以避免的建筑   在某些情况下,并没有简单的方法来修改代码来抑制   警告。其中一些是由-Wextra启用的,但其中很多都启用了   必须单独启用。

我想问题是哪些?也许您可以 grep 以-W开头的所有行的页面,并获得警告标志的完整列表。然后将其与-Wall-Wextra下的列表进行比较。还有-Wpedantic,虽然你显然想要更加迂腐=)

答案 6 :(得分:3)

  

我仍然不知道这份清单是否全面。

可能是,但唯一100%全面的列表是编译器的实际来源。但是,海湾合作委员会!我不知道是否所有命令行参数都收集在一个地方或分散在几个源文件中。另请注意,一些警告用于预处理器,一些用于实际编译器,一些用于链接器(这是一个完全独立的程序,可在binutils包中找到),因此它们很可能是分散的。