What are the useful GCC flags for C?
Solution 1:
Here are mine:
-
-Wextra
,-Wall
: essential. -
-Wfloat-equal
: useful because usually testing floating-point numbers for equality is bad. -
-Wundef
: warn if an uninitialized identifier is evaluated in an#if
directive. -
-Wshadow
: warn whenever a local variable shadows another local variable, parameter or global variable or whenever a built-in function is shadowed. -
-Wpointer-arith
: warn if anything depends upon the size of a function or ofvoid
. -
-Wcast-align
: warn whenever a pointer is cast such that the required alignment of the target is increased. For example, warn if achar *
is cast to anint *
on machines where integers can only be accessed at two- or four-byte boundaries. -
-Wstrict-prototypes
: warn if a function is declared or defined without specifying the argument types. -
-Wstrict-overflow=5
: warns about cases where the compiler optimizes based on the assumption that signed overflow does not occur. (The value 5 may be too strict, see the manual page.) -
-Wwrite-strings
: give string constants the typeconst char[
length]
so that copying the address of one into a non-const char *
pointer will get a warning. -
-Waggregate-return
: warn if any functions that return structures or unions are defined or called. -
-Wcast-qual
: warn whenever a pointer is cast to remove a type qualifier from the target type*. -
-Wswitch-default
: warn whenever aswitch
statement does not have adefault
case*. -
-Wswitch-enum
: warn whenever aswitch
statement has an index of enumerated type and lacks acase
for one or more of the named codes of that enumeration*. -
-Wconversion
: warn for implicit conversions that may alter a value*. -
-Wunreachable-code
: warn if the compiler detects that code will never be executed*.
Those marked * sometimes give too many spurious warnings, so I use them on as-needed basis.
Solution 2:
Several of the -f
code generation options are interesting:
-
-fverbose-asm
is useful if you're compiling with-S
to examine the assembly output - it adds some informative comments. -
-finstrument-functions
adds code to call user-supplied profiling functions at every function entry and exit point. -
--coverage
instruments the branches and calls in the program and creates a coverage notes file, so that when the program is run coverage data is produced that can be formatted by thegcov
program to help analysing test coverage. -
-fsanitize={address,thread,undefined}
enables the AddressSanitizer, ThreadSanitizer and UndefinedBehaviorSanitizer code sanitizers respectively. These instrument the program to check for various sorts of errors at runtime.
Previously this answer also mentioned -ftrapv
, however this functionality has been superseded by -fsanitize=signed-integer-overflow
which is one of the sanitizers enabled by -fsanitize=undefined
.
Solution 3:
Always use -O
or above (-O1
, -O2
, -Os
, etc.). At the default optimization level, gcc goes for compilation speed and doesn't do enough analysis to warn about things like unitialized variables.
Consider making -Werror
policy, as warnings that don't stop the compilation tend to be ignored.
-Wall
pretty much turns on the warnings that are very likely to be errors.
Warnings included in -Wextra
tend to flag common, legitimate code. They may be useful for code reviews (though lint-style programs find a lot more pitfalls are more flexible), but I wouldn't turn them on for normal development.
-Wfloat-equal
is a good idea if the developers on the project are unfamiliar with floating point, and a bad idea if they are.
-Winit-self
is useful; I wonder why it's not included in -Wuninitialized
.
-Wpointer-arith
is useful if you have mostly-portable code that doesn't work with -pedantic
.