我想启用GCC拥有的所有警告。(你会认为这很容易…)

你可能会想-墙可能会管用,但不是!你还需要-沃特。 你可能会想-Wextra可能会奏效,但不是!并不是这里列出的所有警告(例如,-Wshadow)都可以通过此命令启用。我仍然不知道这个列表是否全面。

我如何告诉GCC启用(没有if's, and's, or but's!)它所具有的所有警告?


当前回答

你不能。

GCC 4.4.0的手册只是该版本的综合手册,但它确实列出了4.4.0所有可能的警告。不过,它们并不都在你链接的页面上。例如,c++选项或Objective-C选项页面上有一些特定于语言的选项。要找到所有选项,最好查看选项摘要

打开所有选项将包括-Wdouble-promotion,它只与带有32位单精度浮点单元的cpu相关,该单元在硬件中实现浮点运算,但在软件中模拟double。以double方式进行计算将使用软件模拟,并且速度较慢。这与某些嵌入式cpu有关,但与硬件支持64位浮点的现代桌面cpu完全无关。

另一个通常不常用的警告是-Wtraditional,它警告在传统C中具有不同含义(或不起作用)的完美格式的代码,例如“字符串”“连接”或ISO C函数定义!你真的关心与30年前的编译器的兼容性吗?你真的想要一个写int inc(int i) {return i+1的警告吗?} ?

I think -Weffc++ is too noisy to be useful. It's based on the outdated first edition of Effective C++ and warns about constructs which are perfectly valid C++ (and for which the guidelines changed in later editions of the book). I don't want to be warned that I haven't initialized a std::string member in my constructor; it has a default constructor that does exactly what I want. Why should I write m_str() to call it? The -Weffc++ warnings that would be helpful are too difficult for the compiler to detect accurately (giving false negatives), and the ones that aren't useful, such as initializing all members explicitly, just produce too much noise, giving false positives.

Luc Danton提供了一个来自-Waggregate-return的无用警告的好例子,几乎可以肯定,这些警告对c++代码毫无意义。

也就是说,你并不需要所有的警告;你只是觉得你知道。

通读手册,阅读它们,决定您可能想要启用哪些,并尝试它们。无论如何,阅读编译器的手册是一个好东西,走捷径并启用你不理解的警告不是一个很好的主意,特别是如果它是为了避免不得不RTFM。

那些把所有东西都打开的人,可能要么是因为他们毫无头绪,要么是因为一头尖尖头发的老板说“没有警告”。

有些警告很重要,有些则不然。你必须有辨别力,否则你的程序就会一团糟。以-Wdouble-promotion为例。如果你在嵌入式系统上工作,你可能需要这个;如果您使用的是桌面系统,则可能不需要。你想要- wtradition吗?我对此表示怀疑。

参见-Wall-all启用所有警告,关闭为WONTFIX。

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

其他回答

从本页开始:

注意,一些警告标志不是由-Wall暗示的。其中一些 警告用户通常不考虑的结构 有问题,但偶尔你可能想检查一下; 其他人则对一些必要的或难以避免的短语提出警告 有些情况下,并没有简单的方法来修改代码来抑制 的警告。其中一些是通过-Wextra实现的,但大多数是 必须单独启用。

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

我仍然不知道这个列表是否全面。

它可能是,但唯一100%全面的列表是编译器的实际源代码。然而,GCC很大!我不知道所有命令行参数是收集在一个地方还是分散在几个源文件中。还要注意,一些警告是针对预处理器的,一些是针对实际编译器的,还有一些是针对链接器的(链接器是一个完全独立的程序,可以在binutils包中找到),因此它们很可能是分散的。

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

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

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

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

我同意前面的回答,字面上启用所有警告可能没有好处,但是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 -Waddress -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 -Wdesignated-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-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-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 -Wpadded -Wparentheses -Wpedantic -Wpmf-conversions -Wpointer-arith -Wpointer-sign -Wpointer-to-int-cast -Wpragmas -Wproperty-assign-default -Wprotocol -Wreal-q-constant -Wrealloc-lhs -Wrealloc-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 -Wtraditional -Wtraditional-conversion -Wtrampolines -Wtrigraphs -Wtype-limits -Wundeclared-selector -Wundef -Wunderflow -Wuninitialized -Wunknown-pragmas -Wunsafe-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 -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来避免这些问题。

你不能。

GCC 4.4.0的手册只是该版本的综合手册,但它确实列出了4.4.0所有可能的警告。不过,它们并不都在你链接的页面上。例如,c++选项或Objective-C选项页面上有一些特定于语言的选项。要找到所有选项,最好查看选项摘要

打开所有选项将包括-Wdouble-promotion,它只与带有32位单精度浮点单元的cpu相关,该单元在硬件中实现浮点运算,但在软件中模拟double。以double方式进行计算将使用软件模拟,并且速度较慢。这与某些嵌入式cpu有关,但与硬件支持64位浮点的现代桌面cpu完全无关。

另一个通常不常用的警告是-Wtraditional,它警告在传统C中具有不同含义(或不起作用)的完美格式的代码,例如“字符串”“连接”或ISO C函数定义!你真的关心与30年前的编译器的兼容性吗?你真的想要一个写int inc(int i) {return i+1的警告吗?} ?

I think -Weffc++ is too noisy to be useful. It's based on the outdated first edition of Effective C++ and warns about constructs which are perfectly valid C++ (and for which the guidelines changed in later editions of the book). I don't want to be warned that I haven't initialized a std::string member in my constructor; it has a default constructor that does exactly what I want. Why should I write m_str() to call it? The -Weffc++ warnings that would be helpful are too difficult for the compiler to detect accurately (giving false negatives), and the ones that aren't useful, such as initializing all members explicitly, just produce too much noise, giving false positives.

Luc Danton提供了一个来自-Waggregate-return的无用警告的好例子,几乎可以肯定,这些警告对c++代码毫无意义。

也就是说,你并不需要所有的警告;你只是觉得你知道。

通读手册,阅读它们,决定您可能想要启用哪些,并尝试它们。无论如何,阅读编译器的手册是一个好东西,走捷径并启用你不理解的警告不是一个很好的主意,特别是如果它是为了避免不得不RTFM。

那些把所有东西都打开的人,可能要么是因为他们毫无头绪,要么是因为一头尖尖头发的老板说“没有警告”。

有些警告很重要,有些则不然。你必须有辨别力,否则你的程序就会一团糟。以-Wdouble-promotion为例。如果你在嵌入式系统上工作,你可能需要这个;如果您使用的是桌面系统,则可能不需要。你想要- wtradition吗?我对此表示怀疑。

参见-Wall-all启用所有警告,关闭为WONTFIX。

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