GCC编译参数4.8.5

来自泡泡学习笔记
BrainBs讨论 | 贡献2023年7月13日 (四) 08:43的版本 (创建页面,内容为“==-Wall== 这将使所有关于一些用户认为有问题的构建的警告得以启用,而且很容易避免(或修改以防止警告),即使与宏一起使用也是如此。 请注意,不是所有的警告标志都被“-Wall”隐含。其中一些警告标志会警告一些通常用户不会认为有问题的构造,但偶尔你可能希望检查一下;其他一些警告标志会警告一些在某些情况下是必需或难以避免的构造…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)
跳到导航 跳到搜索

-Wall

这将使所有关于一些用户认为有问题的构建的警告得以启用,而且很容易避免(或修改以防止警告),即使与宏一起使用也是如此。


请注意,不是所有的警告标志都被“-Wall”隐含。其中一些警告标志会警告一些通常用户不会认为有问题的构造,但偶尔你可能希望检查一下;其他一些警告标志会警告一些在某些情况下是必需或难以避免的构造,而且没有简单的方法修改代码以抑制警告。其中一些标志通过“-Wextra”启用,但许多标志必须单独启用。


"-Wall" 打开以下警告标志:

-Waddress

提醒可疑的内存地址使用。这些包括在条件表达式中使用函数地址,比如 void func(void); if (func),以及与字符串字面量的内存地址进行比较,比如 if (x == "abc")。这些使用通常表示程序员的错误:函数的地址始终评估为true,所以在条件语句中使用它们通常表示程序员忘记了函数调用中的括号;而与字符串字面量的比较会导致未指定的行为,并且在C中不具备可移植性,所以通常表示程序员意图使用strcmp。此警告已由“-Wall”启用。


-Warray-bounds (only with ‘-O2’)

当‘-ftree-vrp’选项处于活动状态时(默认为‘-O2’及以上),此选项才会生效。它会警告那些始终越界的数组下标。此警告已由‘-Wall’启用。


-Wc++11-compat

警告在ISO C++ 1998和ISO C++ 2011之间意义不同的C++结构,例如,在ISO C++ 1998中是标识符而在ISO C++ 2011中是关键字的情况。此警告会打开‘-Wnarrowing’,并且已由‘-Wall’启用。


-Wchar-subscripts

如果数组的下标类型为char,将发出警告。这是一个常见的错误原因,因为程序员经常忽略了在某些机器上char类型是有符号的。此警告已由‘-Wall’启用。


-Wenum-compare (in C/ObjC; this is on by default in C++)

警告关于不同枚举类型之间的值比较。在C++中,条件表达式中的枚举不匹配也会被诊断,并且默认情况下启用此警告。在C中,此警告已由‘-Wall’启用。


-Wimplicit-int (C and Objective-C only)

当声明没有指定类型时发出警告。此警告已由‘-Wall’启用。


-Wimplicit-function-declaration (C and Objective-C only)

在函数被声明之前使用时发出警告。在C99模式(‘-std=c99’或‘-std=gnu99’)下,默认情况下启用此警告,并且‘-pedantic-errors’会将其转化为错误。此警告也会被‘-Wall’启用。


-Wcomment

警告每当在'/'注释中出现'/'字符序列或在'//'注释中出现反斜杠换行符时。这两种形式具有相同的效果。


-Wformat

检查对printf和scanf等函数的调用,确保提供的参数类型与指定的格式字符串相符,并且格式字符串中指定的转换是合理的。这包括标准函数以及由格式属性指定的其他函数,在printf、scanf、strftime和strfmon(一个X/Open扩展,不在C标准中)系列(或其他特定于目标的系列)中。哪些函数在未指定格式属性的情况下进行检查取决于所选的标准版本,而对未指定属性的函数的检查将被‘-ffreestanding’或‘-fno-builtin’禁用。 格式将与GNU libc版本2.2所支持的格式特性进行检查。这包括所有ISO C90和C99的特性,以及来自Single Unix规范以及一些BSD和GNU扩展的特性。其他库实现可能不支持所有这些特性;GCC不支持对超出特定库限制的特性发出警告。然而,如果使用‘-Wpedantic’和‘-Wformat’一起使用,将会对不在所选标准版本中的格式特性发出警告(但对于strfmon格式不会,因为它们不在任何C标准版本中)。


-Wformat=1

-Wformat

选项等同于‘-Wformat=1’,而‘-Wno-format’等同于‘-Wformat=0’。由于‘-Wformat’还会检查多个函数的空格式参数,因此‘-Wformat’也意味着‘-Wnonnull’。可以通过以下选项禁用格式检查级别的某些方面:‘-Wno-format-contains-nul’、‘-Wno-format-extra-args’和‘-Wno-format-zero-length’。‘-Wformat’已由‘-Wall’启用。


-Wno-format-contains-nul

如果指定了‘-Wformat’,则不会对包含NUL字节的格式字符串发出警告。


-Wno-format-extra-args

如果指定了‘-Wformat’,则不会对printf或scanf格式函数的多余参数发出警告。C标准规定,这类参数将被忽略。 如果未使用的参数位于使用了‘$’操作数编号规范的已使用参数之间,通常仍然会发出警告,因为实现无法知道应该传递给va_arg以跳过未使用的参数的类型。然而,在scanf格式的情况下,如果未使用的参数都是指针,则此选项将抑制警告,因为Single Unix规范允许存在这样的未使用参数。


-Wno-format-zero-length

如果指定了‘-Wformat’,则不会对零长度的格式发出警告。C标准规定,允许存在零长度的格式。


-Wformat=2

启用‘-Wformat’以及其他额外的格式检查。当前等同于‘-Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k’。


-Wformat-nonliteral

如果指定了‘-Wformat’,还会警告格式字符串不是字符串字面量时无法进行检查的情况,除非格式函数以va_list形式接受其格式参数。


-Wformat-security

如果指定了‘-Wformat’,还会警告可能存在安全问题的格式函数的使用情况。目前,对于格式字符串不是字符串字面量且没有格式参数的printf和scanf函数调用会发出警告,例如printf(foo);。如果格式字符串来自不受信任的输入并且包含‘%n’,则可能存在安全漏洞。(这目前是‘-Wformat-nonliteral’所警告的子集,但将来可能会添加到‘-Wformat-security’中的警告不包括在‘-Wformat-nonliteral’中。)


-Wformat-y2k

如果指定了‘-Wformat’,还会警告可能导致只有两位数年份的strftime格式。


-Wmain (only for C/ObjC and unless ‘-ffreestanding’)

如果‘main’的类型可疑,则发出警告。‘main’应该是一个具有外部链接的函数,返回int类型,接受零个参数、两个参数或三个参数,参数类型应适当。在C++中,默认情况下启用此警告,并且通过‘-Wall’或‘-Wpedantic’启用。


-Wmaybe-uninitialized

对于自动变量,如果存在从函数入口到已初始化变量的使用的路径,但存在其他路径,变量在这些路径上未初始化,如果编译器不能证明未初始化路径在运行时不会执行,则发出警告。之所以将这些警告作为可选项,是因为GCC并不足够聪明,无法看到代码可能正确的所有原因,尽管它看起来有错误。以下是一个示例,说明这种情况可能发生的方式:

 {
   int x;
   switch (y)
   {
     case 1: x = 1;
       break;
     case 2: x = 4;
       break;
     case 3: x = 5;
   }
   foo (x);
 }


如果y的值总是1、2或3,那么x总是被初始化的,但是GCC并不知道这一点。为了消除警告,您需要提供一个带有assert(0)或类似代码的默认情况。 此选项还会在非易失性自动变量可能被longjmp调用更改时发出警告。这些警告仅在优化编译时可能出现。 编译器只能看到对setjmp的调用。它无法知道longjmp将在何处被调用;实际上,信号处理程序可以在代码中的任何位置调用它。因此,即使实际上没有问题,您可能会收到警告,因为longjmp实际上不能在可能引起问题的位置被调用。 如果声明所有不会返回的函数为noreturn,可以避免一些虚假的警告。此警告已由‘-Wall’或‘-Wextra’启用。


-Wmissing-braces (only for C/ObjC)

如果聚合或联合的初始化器没有完全使用括号括起来,就发出警告。在以下示例中,变量‘a’的初始化器没有完全使用括号括起来,而变量‘b’的初始化器则完全使用了括号括起来。在C中,此警告已由‘-Wall’启用。

 int a[2][2] = { 0, 1, 2, 3 };
 int b[2][2] = { { 0, 1 }, { 2, 3 } };


此警告已由‘-Wall’启用。


-Wnonnull

当将空指针传递给由nonnull函数属性标记为需要非空值的参数时发出警告。 ‘-Wnonnull’包含在‘-Wall’和‘-Wformat’中。可以使用‘-Wno-nonnull’选项禁用该警告。


-Wparentheses

在某些上下文中省略括号时发出警告,例如在期望真值的上下文中出现赋值语句,或者在嵌套运算符的优先级容易令人困惑的情况下。 还会警告如果出现类似‘x<=y<=z’的比较,这等同于‘(x<=y ? 1 : 0) <= z’,这与普通数学符号的解释不同。 还会对可能引起混淆的if语句的else分支所属的问题发出警告。以下是一个这种情况的示例:

 {
   if (a)
     if (b)
       foo ();
   else
     bar ();
 }


在C/C++中,每个else分支都属于最内层可能的if语句,本例中是if (b)。这通常不是程序员所期望的,如上面的示例所示,体现在程序员选择的缩进上。当存在混淆的可能性时,GCC在指定该标志时发出警告。要消除警告,请在最内层的if语句周围添加显式的大括号,以确保else不会属于包围的if语句。结果代码如下所示:

 {
   if (a)
   {
     if (b)
       foo ();
     else
       bar ();
   }
 }


还会对使用GNU扩展的?:操作符的危险用法发出警告,即省略了中间操作数。当?:操作符的条件是一个布尔表达式时,省略的值始终为1。通常,程序员期望它是条件表达式内部计算的值。 此警告已由‘-Wall’启用。


-Wpointer-sign

将指针参数传递或赋值给不同的有符号性进行警告。这个选项只支持C和Objective-C。它会被“-Wall”和“-Wpedantic”隐含,可以通过“-Wno-pointer-sign”来禁用。


-Wreorder

在代码中成员初始化器的顺序与它们被执行的顺序不匹配时发出警告。例如:

 struct A {
   int i;
   int j;
   A(): j (0), i (1) { }
 };


编译器会重新排列成员初始化器的顺序,以匹配成员的声明顺序,并发出相应的警告。这个警告通过“-Wall”启用。


-Wreturn-type

当一个函数被定义为默认返回类型为int时发出警告。


还会在返回类型不是void的函数中的任何没有返回值的return语句上发出警告(函数体结尾处的控制流穿透被视为没有返回值),以及在返回类型为void的函数中有带有表达式的return语句。


对于C++,没有返回类型的函数总是会产生诊断消息,即使指定了“-Wno-return-type”。唯一的例外是“main”函数和系统头文件中定义的函数。


-Wsequence-point

对于由于违反C和C++标准中的序列点规则而导致语义不明确的代码发出警告。


C和C++标准以序列点为基础定义了C/C++程序中表达式的求值顺序,序列点表示程序执行部分之间的部分顺序:在序列点之前执行的部分和在序列点之后执行的部分。序列点发生在完整表达式的求值之后(它不是更大表达式的一部分),在逻辑与(&&)、逻辑或(||)、条件运算符(?:)或逗号运算符的第一个操作数的求值之后,在调用函数之前(但在求值其参数和表示被调用函数的表达式之后),以及其他一些特定的位置。除了序列点规则规定的情况外,表达式的子表达式求值顺序是未指定的。所有这些规则仅描述了部分顺序而不是完全


在序列点之间对象的值修改何时生效是未指定的。行为依赖于此的程序具有未定义的行为;C和C++标准规定:“在前一个和下一个序列点之间,一个对象在通过求值表达式进行的最多一次存储值修改之后。此外,先前的值只能被读取来确定要存储的值。如果程序违反这些规则,则在任何特定的实现上的结果是完全不可预测的。


具有未定义行为的代码示例包括a = a++;、a[n] = b[n++]和a[i++] = i;。一些更复杂的情况不会被此选项诊断,并且它可能偶尔会给出错误的通过结果,但总体上它在检测程序中这种问题方面已经被发现相当有效。


此警告在C和C++中通过“-Wall”启用。


-Wsign-compare (only in C++)

在使用有符号值转换为无符号值时,比较有符号值和无符号值可能会产生错误结果时发出警告。此警告也被“-Wextra”启用;要在不包括此警告的情况下获得“-Wextra”的其他警告,请使用“-Wextra -Wno-sign-compare”。


-Wstrict-aliasing

此选项仅在‘-fstrict-aliasing’启用时有效。它警告可能会违反编译器用于优化的严格别名规则的代码。该警告不能捕获所有情况,但会尝试捕获较常见的陷阱。它包含在‘-Wall’中。它等效于‘-Wstrict-aliasing=3’。


-Wstrict-overflow=1

此选项仅在‘-fstrict-overflow’启用时有效。它警告编译器基于有符号溢出不会发生的假设进行优化的情况。需要注意的是,它并不警告所有可能发生溢出的情况:只有在编译器实现了某些优化的情况下才会发出警告。因此,此警告取决于优化级别。


如果涉及的变量的值确实不会发生溢出,那么假设有符号溢出不会发生的优化是完全安全的。因此,此警告可能会给出错误的阳性结果:对实际上没有问题的代码发出警告。为了帮助关注重要问题,定义了几个警告级别。对于在估计循环需要多少次迭代时使用未定义的有符号溢出的情况,特别是确定循环是否被执行的情况,没有发出警告。


Wstrict-overflow=1警告一些既可疑又容易避免的情况。例如,对于‘-fstrict-overflow’,编译器将x + 1 > x简化为1。此级别的‘-Wstrict-overflow’通过‘-Wall’启用;较高级别的警告则不会自动启用,必须明确请求。


-Wswitch

在switch语句的索引为枚举类型并且缺少对该枚举的一个或多个命名代码的case时发出警告。(有默认标签的情况下不会发出此警告)。当使用此选项时,枚举范围之外的case标签也会引发警告(即使有默认标签)。此警告通过“-Wall”启用。


-Wtrigraphs

如果遇到可能改变程序含义的三字符序列(注释中的三字符序列不会被警告),则发出警告。此警告通过“-Wall”启用。


-Wuninitialized

在使用未初始化的自动变量或可能被setjmp调用覆盖的变量时发出警告。在C++中,如果非静态引用或非静态的“const”成员出现在没有构造函数的类中,则发出警告。如果您想要对在其自身初始化程序中使用未初始化变量的代码发出警告,请使用“-Winit-self”选项。


对于结构体、联合体或数组变量的各个未初始化或被覆盖的元素以及整体未初始化或被覆盖的变量,会出现这些警告。对于声明为volatile的变量或元素,不会发出这些警告。由于这些警告依赖于优化,具体发出警告的变量或元素取决于使用的精确优化选项和GCC版本。


需要注意的是,如果一个变量仅用于计算一个从未使用的值,可能不会出现警告,因为在警告打印之前,这样的计算可能会被数据流分析删除。


-Wunknown-pragmas

在遇到GCC不理解的#pragma指令时发出警告。如果使用了这个命令行选项,甚至会对系统头文件中的未知#pragma指令发出警告。如果只有通过“-Wall”命令行选项启用警告,则不会发生这种情况。


-Wunused-function

在声明但未定义静态函数或未使用非内联的静态函数时发出警告。此警告通过“-Wall”启用。


-Wunused-label

在声明但未使用标签时发出警告。此警告通过“-Wall”启用。


要抑制此警告,请使用“unused”属性。


-Wunused-value

在语句计算出一个明确未使用的结果时发出警告。要抑制此警告,请将未使用的表达式转换为‘void’类型。这包括不包含副作用的表达式语句或逗号表达式中的左侧。例如,表达式‘x[i,j]’会引发警告,而‘x[(void)i,j]’不会引发警告。


此警告通过‘-Wall’启用。


-Wunused-variable

除了变量的声明之外,如果一个局部变量或非常量静态变量未被使用时,发出警告。此警告通过“-Wall”启用。


要抑制此警告,请使用“unused”属性。


-Wvolatile-register-var

如果声明了一个寄存器变量为volatile,则发出警告。volatile修饰符不能阻止所有可能消除对寄存器变量的读取和/或写入的优化。此警告通过“-Wall”启用。


-Wextra

这将启用一些额外的警告标志,这些标志不被“-Wall”启用。(此选项以前被称为“-W”。旧名称仍然受支持,但新名称更具描述性。)


选项‘-Wextra’还会针对以下情况打印警告信息:

  • 使用‘<’、‘<=’、‘>’或‘>=’将指针与整数零进行比较。
  • (仅适用于C++)在条件表达式中同时出现枚举器和非枚举器。
  • (仅适用于C++)存在模糊的虚基类。
  • (仅适用于C++)对已声明为“register”的数组进行下标引用。
  • (仅适用于C++)获取已声明为“register”的变量的地址。
  • (仅适用于C++)在派生类的拷贝构造函数中未初始化基类。


-Wclobbered

警告可能会被'longjmp'或'vfork'改变的变量。


-Wempty-body

如果在if、else或do while语句中出现空的代码块,会发出警告。


-Wignored-qualifiers

如果函数的返回类型具有诸如const之类定符,则发出警告。对ISO C而言,此类类型限定符没有效果,因为函数返回的值不是左值。对于C++,此警告仅针对标量类型或void类型。ISO C禁止在函数定义中使用限定的void返回类型,因此即使没有此选项,此类返回类型也始终会收到警告。


-Wmissing-field-initializers

如果结构体的初始化器缺少一些字段,则发出警告。例如,下面的代码会引发此类警告,因为x.h会被隐式地初始化为零:

struct s { int f, g, h; };
struct s x = { 3, 4 };


这个选项不会对指定初始化器发出警告,因此下面的修改不会触发警告:

struct s { int f, g, h; };
struct s x = { .f = 3, .g = 4 };


-Wmissing-parameter-type (C only)

在K&R风格的函数中,函数参数被声明时没有类型说明符:

void foo(bar) { }


-Wold-style-declaration (C only)

根据C标准,在声明中警告过时用法。例如,如果存储类别说明符(如static)不是声明中的第一项,则发出警告。


-Woverride-init

在使用指定初始化器时,如果一个没有副作用的已初始化字段被覆盖,则发出警告。


-Wsign-compare

当使用有符号值与无符号值进行比较时,如果将有符号值转换为无符号值可能导致结果不正确,则发出警告。


-Wtype-limits

如果由于数据类型的有限范围导致比较始终为真或始终为假,请发出警告,但不要对常量表达式发出警告。例如,如果使用'<'或'>='将无符号变量与零进行比较,请发出警告。


-Wuninitialized

如果在使用自动变量之前没有对其进行初始化,或者变量可能会被setjmp调用改变,请发出警告。C++中,如果一个非静态引用或非静态的'const'成员出现在没有构造函数的类中,请发出警告。如果您想警告代码在其自身初始化程序中使用未初始化变量的值,请使用'-Winit-self'选项。这些警告适用于结构体、联合体或数组变量的单个未初始化或丢失的元素,以及整个未初始化或丢失的变量。它们不适用于声明为volatile的变量或元素。由于这些警告取决于优化,具体有哪些变量或元素会有警告取决于使用的精确优化选项请注意,对于仅用于计算其本身从未使用的值的变量,可能没有警告,因为在打印警告之前,此类计算可能会被数据流分析删除。


-Wunused-parameter (only with ‘-Wunused’ or ‘-Wall’)

当一个变量在函数参数声明之外没有使用,请发出警告。要消除这个警告,请使用'unused'属性。


-Wunused-but-set-parameter (only with ‘-Wunused’ or ‘-Wall’)

在函数参数被赋值但未使用(除了声明之外)时,请发出警告。要消除这个警告,请使用'unused'属性。