Best Compiler Warning Level For C/C++ Compilers

How to enable the highest warning level in GCC compiler(Boost is heavily used)

Contrary to cl which has 4 levels, gcc only has a set of options that you can turn on or off.

As mentioned by others, the -Wall is the default, which turns on many warnings already. The -pedantic option adds a few more. And -Wextra yet another group...

But to really capture many warnings, you'll have to add many manually.

There is a set I like to use, although someone told me that some of those were contradictory, I find that list rather good for my development work:

-Werror -Wall -Wextra -pedantic -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wundef -Wno-unused -Wno-variadic-macros -Wno-parentheses -fdiagnostics-show-option

Note that I make use of -Werror because otherwise you get warnings and tend to ignore them. With -Werror, no more ignoring anything! Write pristine code and your software is much more likely to work as expected.

Best practices regarding warning outputs when compiling in gcc?

  1. The more professional you become the more warnings you strive to enable. My current favorite set is -Wall -Wextra -pedantic which gives a good average.

    If you think you receive a false warning, think again. Almost always the compiler is right. Until you become an intimate expert with the C standard you better ask, for example here on SO.

    Some think that -Werror has some value, and for their development process they are probably right. Since I use some kind of build control software (namely "make") I don't need it, because GCC returns non-zero values on warnings, too.

  2. All other flags depend on the purpose of the command. Some examples:

    • -o is great to define the name of the output file.
    • (EDIT)-O… sets the optimization level; some years ago -O3 might have some problems but today it should be fine.
    • -s strips the debug information from the output; good for the release version.
    • -g includes debug information to the output; there are variants depending on your goal.
    • -Wl,--wrap… is really sophisticated for special debugging and/or testing; read its documentation.

Why should I always enable compiler warnings?

Why should I enable warnings?

C and C++ compilers are notoriously bad at reporting some common programmer mistakes by default, such as:

  • forgetting to initialise a variable
  • forgetting to return a value from a function
  • arguments in printf and scanf families not matching the format string
  • a function is used without being declared beforehand (C only)

These can be detected and reported, just usually not by default; this feature must be explicitly requested via compiler options.

How can I enable warnings?

This depends on your compiler.

Microsoft C and C++ compilers understand switches like /W1, /W2, /W3, /W4 and /Wall. Use at least /W3. /W4 and /Wall may emit spurious warnings for system header files, but if your project compiles cleanly with one of these options, go for it. These options are mutually exclusive.

Most other compilers understand options like -Wall, -Wpedantic and -Wextra. -Wall is essential and all the rest are recommended (note that, despite its name, -Wall only enables the most important warnings, not all of them). These options can be used separately or all together.

Your IDE may have a way to enable these from the user interface.

Why should I treat warnings as errors? They are just warnings!

A compiler warning signals a potentially serious problem in your code. The problems listed above are almost always fatal; others may or may not be, but you want compilation to fail even if it turns out to be a false alarm. Investigate each warning, find the root cause, and fix it. In the case of a false alarm, work around it — that is, use a different language feature or construct so that the warning is no longer triggered. If this proves to be very hard, disable that particular warning on a case by case basis.

You don't want to just leave warnings as warnings even if all of them are false alarms. It could be OK for very small projects where the total number of warnings emitted is less than 7. Anything more, and it's easy for a new warning to get lost in a flood of old familiar ones. Don't allow that. Just cause all your project to compile cleanly.

Note this applies to program development. If you are releasing your project to the world in the source form, then it might be a good idea not to supply -Werror or equivalent in your released build script. People might try to build your project with a different version of the compiler, or with a different compiler altogether, which may have a different set of warnings enabled. You may want their build to succeed. It is still a good idea to keep the warnings enabled, so that people who see warning messages could send you bug reports or patches.

How can I treat warnings as errors?

This is again done with compiler switches. /WX is for Microsoft, most others use -Werror. In either case, the compilation will fail if there are any warnings produced.

Is this enough?

Probably not! As you crank up your optimisation level, the compiler starts looking at the code more and more closely, and this closer scrutiny may reveal more mistakes. Thus, do not be content with the warning switches by themselves, always use them when compiling with optimisations enabled (-O2 or -O3, or /O2 if using MSVC).

What are the useful GCC flags for C?

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 the gcov 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.

How can I turn on (literally) ALL of GCC's warnings?

You can't.

The manual for GCC 4.4.0 is only comprehensive for that version, but it does list all the possible warnings for 4.4.0. They're not all on the page you link to though. For instance, some language-specific options are on the pages for C++ options or Objective-C options. To find them all, you're better off looking at the Options Summary

Turning on everything would include -Wdouble-promotion which is only relevant on CPUs with a 32-bit single-precision floating-point unit which implements float in hardware, but emulates double in software. Doing calculations as double would use the software emulation and be slower. That's relevant for some embedded CPUs, but completely irrelevant for modern desktop CPUs with hardware support for 64-bit floating-point.

Another warning that's not usually useful is -Wtraditional, which warns about perfectly well formed code that has a different meaning (or doesn't work) in traditional C, e.g., "string " "concatenation", or ISO C function definitions! Do you really care about compatibility with 30 year old compilers? Do you really want a warning for writing int inc(int i) { return i+1; }?

I think -Weffc++ is too noisy to be useful. It's based on the outdated first edition of Effective C++ and warns about constructs which are perfectly valid C++ (and for which the guidelines changed in later editions of the book). I don't want to be warned that I haven't initialized a std::string member in my constructor; it has a default constructor that does exactly what I want. Why should I write m_str() to call it? The -Weffc++ warnings that would be helpful are too difficult for the compiler to detect accurately (giving false negatives), and the ones that aren't useful, such as initializing all members explicitly, just produce too much noise, giving false positives.

Luc Danton provided a great example of useless warnings from -Waggregate-return that almost certainly never makes sense for C++ code.

I.e., you don't really want all warnings; you just think you do.

Go through the manual, read about them, decide which you might want to enable, and try them. Reading your compiler's manual is a Good ThingTM anyway, taking a shortcut and enabling warnings you don't understand is not a very good idea, especially if it's to avoid having to RTFM.

Anyone who just turns on everything is probably either doing so because they're clueless because or a pointy-haired boss said "no warnings."

Some warnings are important, and some aren't. You have to be discriminating or you mess up your program. Consider, for instance, -Wdouble-promotion. If you're working on an embedded system you might want this; if you're working on a desktop system you probably don't. And do you want -Wtraditional? I doubt it.

See also -Wall-all to enable all warnings which is closed as WONTFIX.

In response to DevSolar's complaint about makefiles needing to use different warnings depending on compiler version, if -Wall -Wextra isn't suitable then it's not difficult to use compiler-specific and version-specific CFLAGS:

compiler_name := $(notdir $(CC))
ifeq ($(compiler_name),gcc)
compiler_version := $(basename $(shell $(CC) -dumpversion))
ifeq ($(compile_name),clang)
compiler_version := $(shell $(CC) --version | awk 'NR==1{print $$3}')
# ...
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))

C / C++ compiler warnings: do you clean up all your code to remove them or leave them in?

I would clean up any warning.
Even the ones that you know are harmless (if such a thing exists) will give a bad impression of you to whoever will compile the code.

It one of the "smelly" signs I would look for if I had to work on someone else code.

If not real errors or potential future issues, it would be a sign of sloppiness

Related Topics

Leave a reply