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

我希望启用 – 从字面上 – GCC 所有的警告。 (你会认为这很容易…)

  • 你会想 – 可能会做的伎俩,但不是! 还需要-Wextra

  • 你会想-Wextra可能会诀窍,但不是! 并非所有列出的警告(例如-Wshadow )都是由此启用的。 而且我还不知道这个清单是否全面。

我如何告诉GCC启用(如果没有,还有或者是) 所有的警告?

你不能。

GCC 4.4.0的手册仅适用于该版本,但它列出了所有可能的4.4.0警告。 它们并不是全部在你链接到的页面上,例如一些语言特定的选项在C ++选项或者Obj-C选项的页面上。 要find他们,你最好看看选项摘要

打开所有的东西都会包括-Wdouble-promotion ,它只与一个32位单精度浮点单元的CPU相关,这个浮点单元在硬件上实现float运算,而在软件上则是double精度浮点运算。 做double计算会使用软件仿真,速度会变慢。 这与某些embedded式CPU相关,但与现代桌面CPU完全无关,并且硬件支持64位浮点。

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

我认为-Weffc++太吵了,没有用处,它基于Effective C ++的过时的第一版,并警告关于构造是完全有效的C ++(本书后面的版本中指导原则会改变)。我不想要警告我没有在我的构造函数中初始化一个std::string成员; 它有一个默认的构造函数,正是我想要的,为什么我应该写m_str()来调用它? 对于编译器来说, -Weffc++警告对于准确检测(给出错误的否定)太困难了,而那些没有用处的警告,比如明确地初始化所有成员,只会产生太多的噪声,给出误报。

Luc Danton提供了来自-Waggregate-return的无用警告的一个很好的例子 ,对于C ++代码几乎肯定没有任何意义。

即你不是真的想要所有的警告,你只是想你。

阅读手册,阅读有关它们,决定你想启用,尝试它们。 无论如何,阅读你的编译器的手册是一件好事TM ,做一个捷径,并启用你不明白的警告不是一个好主意,特别是如果是为了避免RTFM。

任何人只要打开所有的东西 ,可能是因为他们无能为力,或者一个尖头的老板说“没有任何警告”。

一些警告是重要的,有些则不是。 你必须是歧视或你搞砸了你的程序。 考虑一下,例如, -Wdouble-promotion 。 如果你在embedded式系统上工作,你可能需要这个; 如果你在桌面系统上工作,你可能不会。 你想要 – 传统? 我对此表示怀疑。

编辑:另请参阅-Wall-all启用所有以WONTFIXclosures的警告 。

编辑2:为了响应DevSolar关于makefile需要根据编译器版本使用不同警告的抱怨,如果-Wall -Wextra不合适,那么使用编译器特定的和版本特定的CFLAGS并不困难:

 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)) 

我同意以前的答案,可能并不是所有的警告都是有益的,但GCC确实提供了一个相当方便的方法来实现这一点。 命令

 gcc -Q --help=warning 

提供了所有支持的警告选项的列表以及是否处于活动状态的信息。 这可以用来找出哪些选项(不)由例如-Wall-Wextra启用

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

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

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

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

-Wabi -Wabi-tag -Waddress -Waggregate-return -Waggressive-loop-optimizations -waliasing -Walign-commons -Wampersand -Warray-bounds -Warray-temporaries -Wassign-intercept -Wattributes -Wbad-function-cast -Wool-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 -Wwwbbered -Wcomment -Wcompare-reals -Wconally-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 -Wdesignated-init -Wdisabled-optimization -Wdiscarded-array-qualifiers -Wdiscarded-qualifiers -Wdiv-by-zero -Wdouble-promotion -Weffif-labels -Wenum-compare -Wextra -Wffloat-equal -Wformat-contains-nul -Wformat-extra-args -Wformat-nonliteral -Wformat-security-Wformat-signedness – 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-初始化-Wline-truncation -Wliteral-suffix -Wiki-not-括号-Wiki-op -Wlong-long -Wmain -Wmaybe-uninitialized -Wmemset-transposed-args -Wmissing-braces -Wmissing-declarations -Wmissing-field-initializers- Wmissing-include-dirs-Wmissing-parameter-type-Wiringing-prototypes -Wmultichar -Warrowing -Winceted-externs -Wooexcept -Won-template-friend -Wnon-virtual-dtor -Wunnull -Wodr -Wold-style-cast -Wold- style-declaration -Wold-style-definition -Wopenmp-simd -Woverflow -Woverlength-strings -Woverloaded-virtual -Woverride-init -Wpacked -Wpacked-bitfield-compat -Wpadde wpaintheses-wpedantic -wpmf-conversions -Winterinter-arith -Winter-sign -Winterinter-to-int-cast -Wpragmas -Wproperty-assign-default -Wprotocol -Wreal -q-constant -Wrealloc-lhs -Wrealloc-lhs-全部 – 冗余 – 删除 – 三阶 – 反转 – 局部 – 地址 – 反转 – select – 顺序点 – 虚线 – 虚线 – 虚拟 – 虚线 – 虚线 – 虚线 – 虚线 – 虚线 – 虚线 – Wsize-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 -Wwitch -Wwitch-bool -Wswitch-default -Wswitch -enum -Wsync-nand -Wsynth -Wsystem-标题-Wtabs -Wtarget-lifetime -Wtraditional -Wtraditional-conversion -Wtrampolines -Wtrigraphs -Wtype-limits -Wundeclared-selector -Wundef -Wunderflow -Wuninitialized -Wunknown-pragmas -Wuns afe-loop-optimizations-wunsuffixed-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 -Warariadic-mac-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++ ),因此会导致警告。 这些可以通过使用更多的正则expression式来避免,只包含当前语言所允许的选项。

要启用所有的警告是不可能的(除非你会忽略它们,但是为什么呢?)。 例如,假设您使用以下一组标志: -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 

从这个页面 :

请注意,一些警告标志不是由-Wall隐含的。 他们中的一些人警告用户一般不认为有问题的build筑,但有时你可能希望检查; 其他人则警告在某些情况下必须或难以避免的构造,并且没有简单的方法来修改代码来压制警告。 其中一些是由-Wextra启用,但其中许多必须单独启用。

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

而且我还不知道这个清单是否全面。

这可能是,但唯一的100%全面的清单是编译器的实际来源。 不过GCC 很大 ! 我不知道所有的命令行参数是收集在一个地方,还是分散在多个源文件中。 还要注意一些警告是针对预处理器的,一些针对实际的编译器,另一些针对连接器(这是一个完全独立的程序,在binutils包中find),所以它们很可能被分散开来。

有人创build了一套工具来确定给定GCC或Clang版本的完整警告。

对于海湾合作委员会,从你的编译器版本的工具提供的警告的完整列表复制似乎是唯一的方法来确保所有的警告被打开,因为(不像Clang)GCC没有提供 – -Weverything

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

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

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

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

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

如何使用它是非常简单的,基本上是你打开每个警告标志的模块。 并根据需要删除警告 – 有些是非常详细的。 例如: configure.ac

如果你不使用自动工具,你会发现代码打开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 }'