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

我想启用-字面上-<强> < / >强的GCC警告。(你会认为这很容易…)

  • 你可能认为- wall可以做到这一点,但不是!你仍然需要-Wextra

  • 你可能认为-Wextra可以做到这一点,但不是!并不是所有列出的在这里警告(例如,-Wshadow)都是由此启用的。我仍然不知道这个列表是否全面。

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

91119 次浏览

这个页面:

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

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

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

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

你不能。

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

打开一切将包括-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中提供了一个很好的例子的无用警告,几乎可以肯定,这些警告对c++代码毫无意义。

例如,你并不是真的想要所有警告;你只是觉得你知道。

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

任何打开everything的人这样做可能要么是因为他们一无所知,要么是因为一个头发很细的老板说“没有警告”

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

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

在所有警告都启用的情况下编程是不可能的(除非您打算忽略它们,但那又何必呢?)例如,让我们假设您使用下列标志集:-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

我同意前面的回答,字面上启用所有警告可能没有好处,但是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 - waggressiveloop -optimizations -Waliasing - waligni -commons -Wampersand -Warray-bounds -Warray-temporaries - wassigni -intercept -Wattributes -Wbad-function-cast - wbol -compare - wbuiltin - macroredefined - wc++ -compat - wc++ 0x-compat - wc++ 14-compat -Wc-binding-type -Wc90-c99-compat -Wc99-c11-compat -Wcast-align -Wcast-qual - wchar - subscrits -Wcharacter-truncation -Wchkp - wclobtered -Wcomment - wcompare - realals - wconditionically -supported -Wconversion-Wconversion-extra -Wconversion-null -Wcoverage-mismatch -Wcpp - wctor - dr -privacy -Wdate-time -Wdeclaration-after-statement -Wdelete-incomplete -Wdelete-non-virtual-dtor -Wdeprecated -Wdeprecated-declarations - wspecified -init -Wdisabled-optimization - wdiv -by- 0 -Wdouble-promotion - weffc++ -Wempty-body - wdif -labels - wenm -compare -Wextra -Wfloat-equal - wformat -contains- null -Wformat-extra-args -Wformat-nonliteral -Wformat-security- wformat - signiness -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 - winheritic- variadic-ctor -Winit-self -Winline - win -conversion - win -to-pointer-cast - wintrincic -shadow - wintrincics -std -Winvalid-memory-model - winvalid -offset -Winvalid-pch - wskip - missence -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 - wwearing -externs -Wnoexcept -Wnon-template-friend -Wnon-virtual-dtor -Wnonnull -Wodr -Wopenmp-simd -Woverflow -Woverlength-strings - woverloading -virtual- woverrid -init- wwrapped - wwrapped -bitfield-compat - wpadding -Wparentheses -Wpedantic -Wpmf-conversions - wpointer - arwith -Wpointer-sign - wpointer -int-cast -Wpragmas -Wproperty-assign-default -Wprotocol -Wreal-q-constant -Wrealloc-lhs -Wrealloc-lhs-all - wredundent -decls -Wreorder - wrewindow -local-addr - wrewindow -type -Wselector -Wsequence-point -Wshadow -Wshadow-ivar -Wshift-count-negative -Wshift-count-overflow -Wsign-compare -Wsign-promo - wsize -deallocation - wsize -array-argument - wsize -pointer-memaccess-Wstack-protector -Wstrict-null-sentinel - wstrict -prototype -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- wtradition -conversion -Wtrampolines -Wtrigraphs -Wtype-limits - wunknowred -selector -Wundef-Wunderflow -Wuninitialized -Wunknown-pragmas -Wunsafe-loop-optimizations - wunsuffix -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 -Wvarargs -Wvariadic-macros -Wvector-operation-performance -Wvirtual-move-assign -Wvla -Wvolatile-register-var -Wwrite-strings-Wzero-as-null-pointer-constant -Wzerotrip - frequency -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或Clang版本的完整的警告集。

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

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

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

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

我刚刚写了一个m4模块来利用这一点(它也支持铿锵声-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 }'

我从其他帖子中收集了信息,并逐个测试了c++库测试中的警告。

使用列表从Haatschii和他/她获取GCC 11完整列表的方法:

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

在所有这些警告中,有些并不适用于c++,所以这里列出了一些警告和一些适用于我的c++项目测试的最小注释。

考虑到:

  1. 其中一些警告在默认情况下已经开启,无需添加任何选项。
  2. 我不敢说我知道一些警告的真正含义。
  3. 我不建议使用或不使用任何特定的警告。
  4. 有些是评论,但那并不意味着什么。根据需要对它们进行注释或取消注释。(我评论了那些对我的项目没有用处的。)
  5. 有些将不能在GCC 10上工作。
  6. 该列表给出按原样,它可能包含错误或错别字。

这个列表基本上是按字母顺序排列的,为了节省垂直空间,有一些最小的聚类。作为奖励,它被格式化用于CMake项目。

下面是清单:

target_compile_options(
target
PRIVATE
$<CXX_COMPILER_ID:GNU>:
-Werror
-Wall
-Wextra  # (activates -Wunknown-pragmas)
-Wextra-semi
-Wpedantic
# -Wabi=13 -Wabi-tag (maybe important when linking with very old libraries)
-Waddress -Waddress-of-packed-member
# -Waggregate-return (disallow return classes or structs, seems a C-compatibility warning)
-Waggressive-loop-optimizations
-Walloc-zero  # -Walloc-size-larger-than=
-Walloca  # -Walloca-larger-than=
-Wanalyzer-double-fclose -Wanalyzer-double-free -Wanalyzer-exposure-through-output-file -Wanalyzer-file-leak -Wanalyzer-free-of-non-heap -Wanalyzer-malloc-leak -Wanalyzer-mismatching-deallocation -Wanalyzer-null-argument -Wanalyzer-null-dereference -Wanalyzer-possible-null-argument -Wanalyzer-possible-null-dereference -Wanalyzer-shift-count-negative -Wanalyzer-shift-count-overflow -Wanalyzer-stale-setjmp-buffer -Wanalyzer-tainted-array-index -Wanalyzer-too-complex -Wanalyzer-unsafe-call-within-signal-handler -Wanalyzer-use-after-free -Wanalyzer-use-of-pointer-in-stale-stack-frame -Wanalyzer-write-to-const -Wanalyzer-write-to-string-literal
-Warith-conversion
-Warray-bounds -Warray-parameter #  -Warray-bounds=<0,2> -Warray-parameter=<0,2>
-Wattribute-warning -Wattributes
-Wbool-compare -Wbool-operation
-Wbuiltin-declaration-mismatch -Wbuiltin-macro-redefined
-Wc++0x-compat -Wc++14-compat -Wc++17-compat -Wc++1z-compat -Wc++20-compat -Wc++2a-compat
-Wcannot-profile
-Wcast-align -Wcast-align=strict -Wcast-function-type -Wcast-qual
-Wcatch-value  # -Wcatch-value=<0, 3>
-Wchar-subscripts -Wclobbered -Wcomment  # (same as -Wcomments)
-Wconditionally-supported
-Wconversion -Wconversion-null
-Wcoverage-mismatch -Wcpp
# -Wctad-maybe-unsupported  (make ctad explicitly necessary)
-Wctor-dtor-privacy
-Wdangling-else -Wdate-time
-Wdelete-incomplete -Wdelete-non-virtual-dtor
-Wdeprecated -Wdeprecated-copy -Wdeprecated-copy-dtor -Wdeprecated-declarations -Wdeprecated-enum-enum-conversion -Wdeprecated-enum-float-conversion
-Wdisabled-optimization -Wdiv-by-zero -Wdouble-promotion
-Wduplicated-branches -Wduplicated-cond
# -Weffc++ (doesn't allow some advanced techniques, such as CRTP)
-Wempty-body -Wendif-labels
-Wenum-compare -Wenum-conversion
-Wexpansion-to-defined
-Wexceptions
# -Wextra (see above)
-Wfloat-conversion # -Wfloat-equal (disallows float equality)
-Wformat-truncation -Wformat=2 -Wformat-diag -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-signedness -Wformat-truncation -Wformat-y2k -Wformat-zero-length  # -Wformat-overflow=<0,2>
-Wframe-address  # -Wframe-larger-than=<byte-size>
-Wfree-nonheap-object -Whsa -Wif-not-aligned
-Wignored-attributes -Wignored-qualifiers
-Wimplicit-fallthrough#=3  # -Wimplicit-fallthrough=<0,5>
-Winit-self
# -Winline
-Wint-in-bool-context -Wint-to-pointer-cast
-Winvalid-imported-macros
-Winvalid-memory-model -Winvalid-offsetof -Winvalid-pch
-Wignored-qualifiers
# -Wlarger-than=<byte-size>  # (disallow large objects types? in executable)
-Wliteral-suffix
-Wlogical-not-parentheses -Wlogical-op
-Wlong-long -Wlto-type-mismatch -Wmain -Wmaybe-uninitialized
-Wmemset-elt-size -Wmemset-transposed-args
-Wmisleading-indentation
-Wmismatched-dealloc -Wmismatched-new-delete -Wmismatched-tags
-Wmissing-attributes -Wmissing-braces -Wmissing-declarations -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wmissing-profile
-Wmultichar
# -Wmultiple-inheritance (disallows composition by inheritance)
-Wmultistatement-macros
# -Wnamespaces (disallows use of namespaces, seems a C-tool)
-Wnarrowing
-Wnoexcept -Wnoexcept-type
-Wnormalized  #=nfc -Wnormalized=[none|id|nfc|nfkc]
-Wnon-template-friend
-Wnon-virtual-dtor
-Wnonnull -Wnonnull-compare -Wnull-dereference
-Wodr -Wold-style-cast -Wopenmp-simd -Woverflow
-Woverlength-strings -Woverloaded-virtual
-Wpacked -Wpacked-bitfield-compat -Wpacked-not-aligned
# -Wpadded (disallows structs that need padding for alignment)
-Wparentheses
# -Wpedantic (see above)
-Wpessimizing-move -Wplacement-new  #=1  -Wplacement-new=<0,2>
-Wpmf-conversions
-Wpointer-arith -Wpointer-compare
-Wpragmas -Wprio-ctor-dtor -Wpsabi
-Wrange-loop-construct -Wredundant-decls -Wredundant-move -Wredundant-tags -Wregister
-Wreturn-local-addr -Wreturn-type
-Wrestrict -Wreorder
-Wscalar-storage-order -Wsequence-point
-Wshadow -Wshadow-compatible-local -Wshadow-local -Wshadow=compatible-local -Wshadow=local
-Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value -Wshift-overflow  #=1 -Wshift-overflow=<0,2>
-Wsign-compare -Wsign-conversion -Wsign-promo
-Wsized-deallocation
-Wsizeof-array-argument -Wsizeof-array-div -Wsizeof-pointer-div -Wsizeof-pointer-memaccess
-Wstack-protector  # -Wstack-usage=<byte-size>
-Wstrict-aliasing  #=3  -Wstrict-aliasing=<0,3>
-Wstrict-null-sentinel  #=1  -Wstrict-overflow=<0,5>
-Wstrict-overflow  #=1  -Wstrict-overflow=<0,5>
-Wstring-compare
-Wstringop-overflow  #=2  -Wstringop-overflow=<0,4>
-Wstringop-overread -Wstringop-truncation
-Wsubobject-linkage
-Wsuggest-attribute=const -Wsuggest-attribute=format -Wsuggest-attribute=malloc -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wsuggest-final-methods -Wsuggest-final-types
-Wswitch -Wswitch-bool -Wswitch-default -Wswitch-enum -Wswitch-outside-range -Wswitch-unreachable
-Wsync-nand -Wsynth
# -Wsystem-headers (expects system headers to be warning-compliant which they are not)
-Wtautological-compare
# -Wtemplates (disallows templates, C-tool)
-Wtrampolines -Wtrigraphs -Wtsan
-Wtype-limits -Wundef -Wuninitialized
-Wno-unknown-pragmas  # (see above) -Wunknown-pragmas (other compilers need their own pragmas for their warnings)
-Wunreachable-code -Wunsafe-loop-optimizations
-Wunused -Wunused-parameter -Wunused-but-set-variable
# -Wunused-const-variable  #=2
-Wunused-function -Wunused-label -Wunused-local-typedefs -Wunused-macros -Wunused-parameter -Wunused-result -Wunused-value -Wunused-variable
-Wuseless-cast
-Wvarargs -Wvariadic-macros -Wvector-operation-performance -Wvexing-parse -Wvirtual-inheritance -Wvirtual-move-assign
-Wvla -Wvla-parameter
-Wvolatile -Wvolatile-register-var
-Wwrite-strings
-Wzero-as-null-pointer-constant
>
)