223

我想启用——从字面上看——GCC的所有警告。(你会认为这很容易......)

  • 你会认为-Wall可能会成功,但不!还是需要-Wextra的。

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

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

4

7 回答 7

143

你不能。

GCC 4.4.0 的手册仅针对该版本是全面的,但它确实列出了 4.4.0 的所有可能警告。它们并不全部在您链接到的页面上,例如某些特定于语言的选项位于 C++ 选项或 Obj-C 选项的页面上。要找到它们,最好查看选项摘要

打开所有内容将包括-Wdouble-promotion仅与具有 32 位单精度浮点单元的 CPU 相关,该单元在硬件中实现,但在软件中float模拟。doubledouble使用软件仿真一样进行计算并且速度较慢。这与某些嵌入式 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 时。

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

有些警告很重要,有些则不重要。你必须有区别,否则你会搞砸你的程序。例如,考虑-Wdouble-promotion。如果您正在使用嵌入式系统,您可能需要这个;如果你在桌面系统上工作,你可能不会。你想要-Wtraditional吗?我对此表示怀疑。

编辑:另请参阅-Wall-all 以启用所有作为 WONTFIX 关闭的警告。

编辑 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))
于 2012-07-30T11:09:09.887 回答
85

我同意前面的答案,即启用所有警告可能没有好处,但是 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-括号 -Wlogical-op -Wlong-long -Wmain -Wmaybe-uninitialized -Wmemset-transposed-args -Wmissing-braces -Wmissing-declarations -Wmissing-field-initializers -Wmissing-include-dirs -Wmissing-parameter-type -Wmissing 原型-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 -W括号 -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在调用结束时添加适当的选项来避免。

于 2016-01-24T02:00:49.720 回答
16

在启用所有警告的情况下进行编程是根本不可能的(除非您要忽略它们,但是,为什么要麻烦呢?)。例如,假设您使用以下标志集:-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
于 2013-12-21T16:30:36.867 回答
9

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

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

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

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

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

于 2016-02-28T19:04:51.460 回答
7

Gcc 4.3+ 现在有 -Q --help=warnings,你甚至可以指定 --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 }'

于 2016-11-11T21:32:56.460 回答
3

这个页面

请注意,某些警告标志并非由-Wall. 其中一些警告用户通常不认为有问题但偶尔您可能希望检查的结构;其他人警告在某些情况下必须或难以避免的构造,并且没有简单的方法来修改代码以抑制警告。其中一些是由启用的,-Wextra但其中许多必须单独启用。

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

于 2012-07-30T03:00:25.747 回答
3

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

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

于 2012-07-30T06:03:08.923 回答