Warnings: -Weverything and the Kitchen Sink

I am a fan of warnings. By highlighting dangerous or ambiguous areas of our code, warnings provide valuable insight and advice for keeping your programs tidy. Since I like warnings so much, I try to turn on as many of them as possible, while sifting out any annoying warnings like -Wunknown-pragmas.

Many developers are familiar with some of the common warning flags like -Wall, but I'd like to give you a quick refresher on the following flags:

  • -Wall
  • -Wextra
  • -pedantic/-Wpedantic
  • -Weverything (clang only)

-Wall

Many programmers know about the -Wall flag already. Given my inclusion of other flags such as -Wextra and -Weverything, I hope it is clear that -Wall does not actually ALL the warning flags. Regardless, enabling -Wall in your code will provide you with a decent amount of warning coverage and boost your program's resiliency.

According to the GCC manual, the -Wall flag "enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. This also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options."

Here is a full list of the 48 flags enabled by -Wall:

  • -Waddress
  • -Warray-bounds=1 (only with -O2)
  • -Wbool-compare
  • -Wbool-operation
  • -Wc++11-compat
  • -Wc++14-compat
  • -Wcatch-value (C++ and Objective-C++ only)
  • -Wchar-subscripts
  • -Wcomment
  • -Wduplicate-decl-specifier (C and Objective-C only)
  • -Wenum-compare (in C/ObjC; this is on by default in C++)
  • -Wformat
  • -Wint-in-bool-context
  • -Wimplicit (C and Objective-C only)
  • -Wimplicit-int (C and Objective-C only)
  • -Wimplicit-function-declaration (C and Objective-C only)
  • -Winit-self (only for C++)
  • -Wlogical-not-parentheses
  • -Wmain (only for C/ObjC and unless -ffreestanding)
  • -Wmaybe-uninitialized
  • -Wmemset-elt-size
  • -Wmemset-transposed-args
  • -Wmisleading-indentation (only for C/C++)
  • -Wmissing-braces (only for C/ObjC)
  • -Wnarrowing (only for C++)
  • -Wnonnull
  • -Wnonnull-compare
  • -Wopenmp-simd
  • -Wparentheses
  • -Wpointer-sign
  • -Wreorder
  • -Wreturn-type
  • -Wsequence-point
  • -Wsign-compare (only in C++)
  • -Wsizeof-pointer-div
  • -Wsizeof-pointer-memaccess
  • -Wstrict-aliasing
  • -Wstrict-overflow=1
  • -Wswitch
  • -Wtautological-compare
  • -Wtrigraphs
  • -Wuninitialized
  • -Wunknown-pragmas
  • -Wunused-function
  • -Wunused-label
  • -Wunused-value
  • -Wunused-variable
  • -Wvolatile-register-var

-Wextra

After seeing the list of warnings provided by -Wall, you may be wondering why you need any others. -Wextra provides warnings that are helpful but much more pedantic, covering topics such as empty function bodies, unused parameters, and sign mismatches in comparisons. These warnings are often viewed as a nuisance, but they also help eliminate bad coding styles and point out potential bugs (maybe you did intend to use that parameter).

Here's the full list of flags enabled by -Wextra:

  • -Wclobbered
  • -Wempty-body
  • -Wignored-qualifiers
  • -Wimplicit-fallthrough=3
  • -Wmissing-field-initializers
  • -Wmissing-parameter-type (C only)
  • -Wold-style-declaration (C only)
  • -Woverride-init
  • -Wsign-compare (C only)
  • -Wtype-limits
  • -Wuninitialized
  • -Wshift-negative-value (in C++03 and in C99 and newer)
  • -Wunused-parameter (only with -Wunused or -Wall)
  • -Wunused-but-set-parameter (only with -Wunused or -Wall)

Enabling -Wextra also enables warnings for the following conditions:

  • A pointer is compared against integer zero with <, data-preserve-html-node="true" <=, data-preserve-html-node="true" >, or >=.
  • (C++ only) An enumerator and a non-enumerator both appear in a conditional expression.
  • (C++ only) Ambiguous virtual bases.
  • (C++ only) Subscripting an array that has been declared register.
  • (C++ only) Taking the address of a variable that has been declared register.
  • (C++ only) A base class is not initialized in the copy constructor of a derived class.

-Wpedantic

-Wpedantic takes our warnings even further. The -pedantic set contains "all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used." -Wpedantic also rejects certain GNU extensions and C/C++ features that are not ISO-compliant.

The GNU manual notes that many will try to use -Wpedantic to check for ISO C conformance, but keep in mind: -Wpedantic only checks for non-ISO practices for which diagnostics are required or have already been added. Even so, -Wpedantic is a useful flag if you are aiming for ISO C/C++ conformance. Primarily, I enable this flag temporarily to find areas where my programs can be improved.

Clang: -Weverything

Clang helpfully provides a flag called -Weverything. Unlike -Wall, the -Weverything flag really will enable all warnings. This flag is especially useful if you are a warning lover - new warnings will automatically be enabled when you upgrade clang/Xcode.

Turning -Weverything can be an eye-opening experience, even for those who religiously squash warnings. I often turn on -Weverything temporarily to review any of the less-common warnings and see what's worth fixing in my code base.

Turning On Specific Warnings

-Wall and -Wextra provide a very comprehensive set of warnings, but many developers are picky about the warnings they want to deal with in their projects.

Rather than cause strife by turning on more warnings than your team can tolerate, I recommend an alternative approach: start with -Wall (something most developers can stomach) and specifically enable warnings that will benefit your team.

You can enable specific warnings by combining the -W prefix with the warning name, such as:

-Wmissing-prototypes
-Wformat-security

This approach allows you to enable valuable warnings in your project without a flood of other minor warnings that come with enabling something like -Wextra.

Turning Off Specific Warnings

Similar to using the -W prefix with a warning name to enable a warning, you can use the -Wno- prefix to disable a warning explicitly. For example:

-Wno-deprecated-declarations
-Wno-unused-parameter

Disabling warnings explicitly can be useful in cases where the warning behavior cannot be suppressed and is intentional.

Clang: Locally Disabling Warnings

Clang provides even further granular control over disabling warnings using the diagnostic pragma. You can disable warnings over a small region of code:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
    serverAddress->ss_family = host->h_addrtype;
#pragma clang diagnostic pop

I often use this method for including external libraries and headers that have warnings which I won't be fixing.

Isn't -Wall Enough?

Some people struggle even with enabling -Wall, as some of the constructions that cause warnings can be hard to avoid or suppress.

Where possible, it is better to locally disable a warning (like with clang's diagnostic pragma).

Further Reading