Making GCC and other C++ compilers very strict - c++

I'm working on a large collaborative C++ project that is both developed and run on various flavors of Linux, OS X and Windows. We compile across these platforms with GCC, Visual Studio C++ and the Intel C++ compiler. As more and more people start developing code for the project, we're starting to see weird errors in compilation and runtime that are specific to particular compilers on particular operating systems. An example of this is implicit inclusion of headers that certain OS/compiler pairs seem to find for you, accidentally overloading a function from a base class in a derived class.
My goal is to make compilation on GCC more strict and catch more errors across all platforms so that we don't keep running into these problems. Here's my list of flags that I'm thinking about trying out for GCC that I've found via Google and the GCC man pages:
-Wall
-Wextra
-Winit-self
-Wold-style-cast
-Woverloaded-virtual
-Wuninitialized
-Wmissing-declarations
-Winit-self
-ansi
-pedantic
What are the other flags that people use to make GCC (and less importantly Visual Studio C++ and the Intel C++ Compiler) obey a stricter standard of the C++ language? Be specific about which compiler and version you're talking about, as some of these might not be implemented in all versions of all compilers.

Beside the pedantic-error that everyone else suggested, IMO, it's always good to run lint as part of your compile process.
There are some tools out there:
cpplint (free)
gimple lint
coverity
They will save a lot of your time.

You can make pedantic warnings into errors with -pedantic-errors. This will prevent developers from ignoring it. For that matter you could make all warnings into errors as well with -Werror although that can be counter productive in some cases (maybe not in yours though).
Overall, I think, as far as adhering to a strict standard goes, the -pedantic options are the most helpful.

Copy and paste the below line into your master CMake file. The below line comprises almost most useful compiler flags in order to test yourself stricter.
set(CMAKE_CXX_FLAGS "-O0 -fno-elide-constructors -pedantic-errors -ansi -Wextra -Wall -Winit-self -Wold-style-cast -Woverloaded-virtual -Wuninitialized -Wmissing-declarations -Winit-self -std=c++98")
If you don’t use CMake, just copy the flags in double quotes and send them to your compiler.

-pedantic-errors.
See more on gcc(1).

As well as -pendantic, you should also provide a -std switch. If you need a stricter compile then you should know what standard you are trying to conform to. Typically for current C++ this would be -std=c++98. (-ansi performs a similar function in C++ mode, but -std= is more explicit.)

In a similar situation we gave up and moved to the ACE framework, hiding the difference between platforms.

I wrote a blog post on this topic after researching several options. You also need to handle the cases where you are using other libraries, but they are not following strict compilation. Fortunately, there is an easy way to handle them as well. I have been using this extensively in all my projects.
In short, use the following compiler options to turn on very strict mode (below is what I put in CMakeLists.txt):
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra -Wstrict-aliasing -pedantic -fmax-errors=5 -Werror -Wunreachable-code -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 -Wswitch-default -Wundef -Wno-unused -Wno-variadic-macros -Wno-parentheses -fdiagnostics-show-option ${CMAKE_CXX_FLAGS}")
You can read more about how to turn on and off this strict mode for specific portions of code here: http://shitalshah.com/p/how-to-enable-and-use-gcc-strict-mode-compilation/

Related

how to turn on icc/icpc warnings?

I installed Intel Compiler composer_xe_2013_sp1.3.174 on Linux. I am confused about the icc warnings. Feed icc with a simple program main.c as below:
int main(int argc, char **argv) {
int a = 1;
unsigned int b = -22;
if (b = a) {
}
}
I compiled the file with the command: icc -Wall main.c. Surprisingly, the command works silently without any warnings. Do I have to turn on the warnings switch on icc? Thanks
The Intel compiler doesn't really have good presets for warnings the way that gcc does (at least on Linux). The main warning option is -wn where n can be 0 to 5. The default is 1, and 4 & 5 have no meaning on Linux. It also supports some gcc options like -Wall and -Wextra. However:
-Wall is very minimalistic compared to gcc, as you found
-w2 and -w3 enable some useful diagnostics, but also a lot of spam remarks
-diag-disable:remark removes that spam but also a lot of useful diagnostics
In the end -w3 -diag-disable:remark is the best preset that icc has but it is still more minimalistic than gcc -Wall. Instead you need to either start with a minimal set of warnings and build up your own, or start with maximum diagnostics and disable any that get annoying using -wd.
Build Up
The main downside to the first approach is that Intel doesn't really document most of its warnings, so it is hard to know what is available to enable. However, it does support many of the GCC command line flags, so the GCC documentation is a good place to start. For example, here are settings that are relatively close to g++ -Wall, which is convenient if you want to develop with one and have a good chance of a clean build with the other:
icpc -Wall -Warray-bounds -Wchar-subscripts -Wcomment -Wenum-compare -Wformat -Wuninitialized -Wmaybe-uninitialized -Wmain -Wnarrowing -Wnonnull -Wparentheses -Wpointer-sign -Wreorder -Wreturn-type -Wsign-compare -Wsequence-point -Wtrigraphs -Wunused-function -Wunused-but-set-variable -Wunused-variable -Wwrite-strings
This isn't an exact match for gcc -Wall. There are differences between GCC's and ICC's implementation of the above warnings. I was also unable to find ICC options to match these GCC warnings:
-Wformat-contains-nul
-Wunused-label
-Wstrict-overflow
-Wvolatile-register-var
And I intentionally left these out, because the ICC version was much more spammy than GCC:
-Wstrict-aliasing So broad that any use of polymophism will cause this warning
-Wswitch Requires a default even if you have cases for all enumeration values
Trim Down
If GCC parity isn't a concern then the easiest way to learn what warnings ICC has is to enable them all, and then decide whether you like them or not. If you don't like a warning, you can disable it using it's diagnostics number, which often has more granularity that GCC's options do.
icpc -w3 -wd1418,2259
Here are some diagnostics that I have seen disabled in the past:
383: value copied to temporary, reference to temporary used
869: parameter "*" was never referenced
981: operands are evaluated in unspecified order
1418: external function definition with no prior declaration
1572: floating-point equality and inequality comparisons are unreliable
2259: non-pointer conversion may loose significant bits
11074: Inlining inhibited by limit max-size (or max-total-size)
11076: To get full report use -qopt-report=4 -qopt-report-phase ipo
161: disable warning for unrecognized pragmas
But I encourage you to start with them all on and pare down just the ones that are problematic for your code base.
Generally speaking, the best compilation options for a small program your developing is
-Wall -Wextra -std=c11 -pedantic
Contrary to the warning switch's name, Wall does not actually activate all warnings; you use both Wall and Wextra to get the majority of the important warnings.
-std switch sets the standard that the code uses; the most recent one is C11 therefore std=c11. Pedantic is a way to signal to the compiler that you want to write a program that doesn't use compiler-specific extensions. Pedantic requires the std switch and will emit warnings for any syntax, ect. that does not conform to the standard specified by std. Finally, if you want errors instead of warnings for usage of compiler-extension, use -pedantic-errors instead.*
(* - pedantic does not warn about the usage of non-standard libraries like conio.h)
Now if you compile the program with Wall Wextra std=c11 pedantic, you should get 1 warnings:
Warning: Line 4 - Suggest Parenthesis around truthy value (9 out of 10, this means you used = instead == in a comparison context).
If you fix that warning, you'll receive another warning:
Warning: Line 4 - Comparison between Signed and Unsigned Integer without a cast.
Adding an explicit cast or changing b to a normal int will solve this warning.
These days I am pretty happy using this target_options in CMake with icpc 2021.6.0 20220226, I collected them from several sources.
Any additions are welcome.
target_compile_options(
${TEST_EXE}
PRIVATE
$<$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>:
...
>
$<$<AND:$<CXX_COMPILER_ID:GNU>,$<NOT:$<CUDA_COMPILER_ID:NVIDIA>>,$<NOT:$<CUDA_COMPILER_ID:Clang>>>:
...
>
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CUDA_COMPILER_ID:Clang>>:
...
>
$<$<CXX_COMPILER_ID:Intel>: # also IntelLLVM, XL (ibm), XLClang (ibm)
-Werror
-Wall
-Wextra
-diag-disable=remark
-diag-error:3846
-diag-disable=1011 # disables warning missing return at the end of non-void function
-wd161
-Wabi
-Warray-bounds
-Wcast-qual
-Wchar-subscripts
-Wcomment
-Wdeprecated
-Wenum-compare
-Wextra-tokens
-Wformat
-Wformat=2
-Wformat-security
-Wic-pointer
-Wnarrowing
-Wno-return-type
-Wnon-virtual-dtor
-Wnonnull
-Wmaybe-uninitialized
-Wmain
-Wmissing-declarations
-Wmissing-prototypes
-Wmultichar
-Woverloaded-virtual
-Woverflow
-Wparentheses
-Wpointer-arith
-Wpointer-sign
-Wreorder
-Wreturn-type
-Wsequence-point
-Wshadow
-Wsign-compare
-Wshorten-64-to-32
-Wno-strict-aliasing
-Wstrict-prototypes
-Wtrigraphs
-Wtype-limits
-Wuninitialized
-Wunused
-Wunused-but-set-variable
-Wunused-function
-Wunused-parameter
-Wunused-variable
-Wwrite-strings
>
$<$<OR:$<CXX_COMPILER_ID:PGI>,$<CXX_COMPILER_ID:NVHPC>>:
...
>
$<$<CXX_COMPILER_ID:MSVC>:
...
>
)

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

I just read a book which recommends enable the highest warning level in GCC. I just check the doc online, and found there are too much parameters. I want to enable the highest warning level, which parameter should I use?
And we use Boost heavily in our project.
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.
I guess you can use the -Wallswitch

Flags to enable thorough and verbose g++ warnings

Often in C under gcc, I will start with the following set of warning flags (painfully assembled from multiple sources):
-Wall -Wextra -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wbad-function-cast \
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef \
-Wnested-externs -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-parameter \
-Wfloat-equal -pedantic -ansi
I will build (at least my debug versions) with this set of warnings and fix everything I possibly can (usually everything), and then only remove flags if they are either not relevant or not fixable (almost never the case). Sometimes, I'll also add -Werror if I have to step away while compiling.
I'm just picking up C++ (yes, I'm 15 years behind the times), and I'd like to start off on the right foot.
My question is: Does someone have a precompiled similar set of complete warning flags for C++ under g++? (I know many of them will be the same.)
I went through and found the minimal set of includes that should get the maximum level of warning. I then removed from that list the set of warnings that I feel do not actually indicate something bad is happening, or else have too many false positives to be used in a real build. I commented as to why each of the ones I excluded were excluded. This is my final set of suggested warnings:
-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused
Questionable warnings that are present:
I include -Wno-unused because I often have variables that I know I
will use later, but do not yet have the functionality written for.
Removing warnings about that allows me to write in my preferred style
of occasionally deferring the implementation of things. It is useful
to turn that off every once in a while to make sure nothing slipped
through the cracks.
-Wdisabled-optimization seems like a strong user-preference
setting. I just added this one to my build (only for optimized builds
for obvious reasons) and it didn't turn anything up, so it doesn't
seem to be an especially chatty warning, at least for the way I code.
I include it (even though code that triggers this warning isn't
necessarily wrong) because I believe in working with my tools instead
of against them. If gcc is telling me that it cannot optimize code
for the way I wrote it, then I should look at rewriting it. I suspect
that code that triggers this warning could benefit from being more
modular, regardless, so although the code is not technically wrong
(probably), stylistically it likely is.
-Wfloat-equal warns for safe equality comparisons (in particular,
comparison with a non-computed value of -1). An example in my code
where I use this is that I have a vector of float. I go through this
vector, and there are some elements I cannot evaluate yet what they
should be, so I set them to -1.0f (since my problem only uses
positive numbers, -1 is out of the domain). I later go through and
update -1.0f values. It does not easily lend itself to a different
method of operation. I suspect that most people don't have this
problem, and comparison of an exact number in floating point is
probably an error, so I'm including it in the default list.
-Wold-style-cast has a lot of false positives in library code I'm using. In particular, the htonl family of functions used in networking, as well as a Rijndael (AES) encryption implementation I'm using has old-style casts that it warns me about. I intend to replace both of these, but I'm not sure if there is anything else in my code that it will complain about. Most users should probably have this on by default, though.
-Wsign-conversion was a tough one (and almost didn't make the
list). Turning it on in my code generated a huge amount of warnings
(100+). Almost all of them were innocent. However, I have been
careful to use signed integers wherever I wasn't sure, although for
my particular problem domain, I would usually get a slight efficiency
increase using unsigned values due to the large amount of integer
division I do. I sacrificed this efficiency because I was concerned
about accidentally promoting a signed integer to an unsigned and then
dividing (which is not safe, unlike addition, subtraction, and
multiplication). Turning on this warning allowed me to safely change
most of my variables to unsigned types and add a few casts in some
other places. It's currently a little hard to use because the warning
isn't that smart. For instance, if you do unsigned short + (integral
constant expression), that result is implicitly promoted to int. It
then warns about a potential sign problem if you assign that value to
unsigned or unsigned short, even though it's safe. This is
definitely the most optional warning for almost all users.
-Wsign-promo: see -Wsign-conversion.
-Wswitch-default seems pointless (you don't always want a default
case if you've enumerated all possibilities explicitly). However,
turning on this warning can enforce something that is probably a good
idea. For cases where you explicitly want to ignore everything except
the listed possibilities (but other numbers are possible), then put
in default: break; to make it explicit. If you explicitly enumerate
all possibilities, then turning on this warning will help ensure that
you put something like assert (false) to make sure that you've
actually covered all possible options. It lets you be explicit in
what the domain of your problem is and programatically enforces that.
However, you'll have to be careful in just sticking assert (false)
everywhere. It's better than doing nothing with the default case, but
as usual with assert, it won't work in release builds. In other
words, you cannot rely on it to validate numbers that you get from,
say, a network connection or a database that you do not have absolute
control over. Exceptions or returning early are the best way to
handle that (but still require you to have a default case!).
-Werror is an important one for me. When compiling large amounts of
code in a multi-threaded build with multiple targets, it's easy for a
warning to slip by. Turning warnings into errors ensures that I
notice them.
Then there is a set of warnings that are not included in the above list because I did not find them to be useful. These are the warnings and my comments on why I'm not including them in the default list:
Warnings that are absent:
-Wabi is not needed because I'm not combining binaries from different compilers. I tried compiling with it anyway, and it didn't trigger, so it doesn't seem needlessly verbose.
-Waggregate-return is not something that I consider an error. For
instance, it triggers when using a range-based for loop on a vector
of classes. Return value optimization should take care of any
negative effects of this.
-Wconversion triggers on this code: short n = 0; n += 2; The
implicit conversion to int causes a warning when it's then converted
back to its target type.
-Weffc++ includes a warning if all data members are not initialized
in the initializer list. I intentionally do not do this in many
cases, so the set of warnings is too cluttered to be useful. It's
helpful to turn on every once in a while and scan for other warnings,
though (such as non-virtual destructors of base classes). This would
be more useful as a collection of warnings (like -Wall) instead of
a single warning on its own.
-Winline is absent because I don't use the inline keyword for
optimization purposes, just to define functions inline in headers. I
don't care if the optimizer actually inlines it. This warning also
complains if it can't inline a function declared in a class body
(such as an empty virtual destructor).
-Winvalid-pch is missing because I don't use precompiled headers.
-Wmissing-format-attribute is not used because I do not use gnu
extensions. Same for -Wsuggest-attribute and several others
Potentially notable for its absence is -Wno-long-long, which I have
no need for. I compile with -std=c++0x (-std=c++11 in GCC 4.7),
which includes long long integer types. Those stuck back on C++98 /
C++03 may consider adding that exclusion from the warning list.
-Wnormalized=nfc is already the default option, and looks to be the
best.
-Wpadded is turned on occasionally to optimize the layout of
classes, but it is not left on because not all classes have enough
elements to remove padding at the end. In theory I could get some
extra variables for 'free', but it's not worth the extra effort of
maintaining that (if my class size changes, it's not easy to remove
those previously free variables).
-Wstack-protector is not used because I do not use -fstack-protector
-Wstrict-aliasing=3 is turned on by -Wall and is the most
accurate, but it looks like level 1 and 2 give more warnings. In
theory a lower level is a 'stronger' warning, but it's at the cost of
more false positives. My own test code compiled cleanly under all 3
levels.
-Wswitch-enum isn't behavior that I want. I don't want to handle
every switch statement explicitly. It would be useful if the language
had some mechanism to activate this on specified switch statements
(to ensure that future changes to the enum are handled everywhere
that they need to be), but it's overkill for an "all-or-nothing"
setting.
-Wunsafe-loop-optimizations causes too many spurious warnings. It
may be useful to apply this one periodically and manually verify the
results. As an example, it generated this warning in my code when I
looped over all elements in a vector to apply a set of functions to
them (using the range-based for loop). It is also warning for the
constructor of a const array of const std::string (where this is no
loop in user code).
-Wzero-as-null-pointer-constant and -Wuseless-cast are
GCC-4.7-only warnings, which I will add when I transition to GCC 4.7.
I've filed a few bug reports / enhancement requests at gcc as a result of some of this research, so hopefully I'll be able to eventually add more of the warnings from the "do not include" list to the "include" list. This list includes all warnings mentioned in this thread (plus I think a few extra). Many of the warnings not explicitly mentioned in this post are included as part of another warning I do mention. If anyone notices any warnings that are excluded from this post entirely, let me know.
edit: It looks like I had missed several (which I have now added in). There is actually a second page at http://gcc.gnu.org that is quite well hidden. General warning options and C++ options (scroll down to the bottom for warnings)
D'oh, all of my original searches turned up 99% of posts on how to suppress warnings (scarily enough), but I just ran across this comment, which has this lovely set of flags (some less relevant):
Cross checked with:
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
-g -O -Wall -Weffc++ -pedantic \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security \
-Wformat-y2k \
-Wimplicit -Wimport -Winit-self -Winline \
-Winvalid-pch \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings
So, I think that's a good starting point. Didn't realize this was a dupe, but at least it was deeply buried. :-)
Some of those are already included in -Wall or -Wextra.
A good base setup for C is:
-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror
and for C++
-ansi -pedantic -Wall -Wextra -Weffc++
(skipping -Werror for C++ since -Weffc++ has some annoyances)
Try
export CFLAGS="`gcc --help=warnings | grep '\-W' | awk '{print $1 \" \"}' |
sort | uniq` -pedantic -fdiagnostics-show-option -Werror"
That's a quick and dirty start which will definitely need some tuning; for one thing, even if you call the compiler by the appropriate name for your language (e.g. g++ for C++), you will get warnings that don't apply to that language (and the compiler will throw up its hands and refuse to continue until you remove the warning).
Another thing is that I added in -Werror, because if you aren't fixing the warnings, why do you care about turning them on? You can also take warnings out of the list. (For example, I almost never use -Waggregate-return with C++.)
Some warnings won't do anything without other performance related options (-Wstack-protector). -fdiagnostics-show-option and the GCC manual are your friends.
By the way, some warnings are mutually exclusive; in particular using -Wtraditional and -Wold-style-definition along with -Werror, will not compile.
In my Clion's CmakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(cpp17)
set(CMAKE_CXX_STANDARD 17)
set(GCC_COVERAGE_COMPILE_FLAGS "-std=c++17 -Wall -Weffc++ -Wno-error=effc++ -pedantic \
-Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-newline-eof \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security \
-Wformat-y2k \
-Wimplicit -Wimport -Winit-self -Winline -Winvalid-pch \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )
add_executable(cpp17 main.cpp)

What does "-Wall" in "g++ -Wall test.cpp -o test" do?

-o changes the output filename (I found that using --help)
But I can't find out what -Wall does?
It's short for "warn all" -- it turns on (almost) all the warnings that g++ can tell you about. Typically a good idea, especially if you're a beginner, because understanding and fixing those warnings can help you fix lots of different kinds of problems in your code.
See man gcc.
-Wall turns on these warnings:
-Waddress -Warray-bounds (only with -O2) -Wc++0x-compat -Wchar-subscripts
-Wenum-compare (in C/Objc; this is on by default in C++) -Wimplicit-int (C and
Objective-C only) -Wimplicit-function-declaration (C and Objective-C only)
-Wcomment -Wformat -Wmain (only for C/ObjC and unless -ffreestanding)
-Wmissing-braces -Wnonnull -Wparentheses -Wpointer-sign -Wreorder -Wreturn-type
-Wsequence-point -Wsign-compare (only in C++) -Wstrict-aliasing
-Wstrict-overflow=1 -Wswitch -Wtrigraphs -Wuninitialized -Wunknown-pragmas
-Wunused-function -Wunused-label -Wunused-value -Wunused-variable
-Wvolatile-register-var
-Wextra contains:
-Wclobbered -Wempty-body -Wignored-qualifiers -Wmissing-field-initializers
-Wmissing-parameter-type (C only) -Wold-style-declaration (C only) -Woverride-init
-Wsign-compare -Wtype-limits -Wuninitialized -Wunused-parameter (only with -Wunused
or -Wall) -Wunused-but-set-parameter (only with -Wunused or -Wall)
There are many more warnings which you have to turn on explicitly.
E.g. for our C code we use:
-Wall -Wextra -Waggregate-return -Wcast-align -Wcast-qual -Wdisabled-optimization -Wdiv-by-zero -Wendif-labels -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wimplicit -Wimport -Winit-self -Winline -Winvalid-pch -Wjump-misses-init -Wlogical-op -Werror=missing-braces -Wmissing-declarations -Wno-missing-format-attribute -Wmissing-include-dirs -Wmultichar -Wpacked -Wpointer-arith -Wreturn-type -Wsequence-point -Wsign-compare -Wstrict-aliasing -Wstrict-aliasing=2 -Wswitch -Wswitch-default -Werror=undef -Wno-unused -Wvariadic-macros -Wwrite-strings -Wc++-compat -Werror=declaration-after-statement -Werror=implicit-function-declaration -Wmissing-prototypes -Werror=nested-externs -Werror=old-style-definition -Werror=strict-prototypes
or just the set of warnings with https://www.gnu.org/software/autoconf-archive/ax_compiler_flags.html
Sadly enough none of the answers is quoting the actually relevant part of manual, which really brings it to a point:
This 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.
[...]
Note that some warning flags are not implied by -Wall. Some of them warn
about constructions that users generally do not consider questionable, but which
occasionally you might wish to check for; others warn about constructions that
are necessary or hard to avoid in some cases, and there is no simple way to
modify the code to suppress the warning. Some of them are enabled by -Wextra
but many of them must be enabled individually.
Ergo:
-Wall does not mean "all warnings".
It does also not mean "(almost) all", not by a long shot.
It does mean a set of individual options that is bound to change.
Bottom line, it is about the absolute minimum of warnings you should set. While -Wall -Wextra is better, it's still not making use of all the error checking your compiler can do for you.
Personally I wouldn't go for less than -Wall -Wextra -Wfloat-equal -Wundef -Wcast-align -Wwrite-strings -Wlogical-op -Wmissing-declarations -Wredundant-decls -Wshadow -Woverloaded-virtual. All my current projects actually use a list of warnings longer than that (without triggering any of them). And I do check the manual on every major release for new options. The compiler is your friend. Use whatever diagnostics it can offer you.
It enables warnings which are deemed useful and easy to avoid at the source by gcc writers. There is also -W (-Wextra in newer releases) which are deemed useful but for which work-arounding false positives can be difficult or result in clumsy code.
gcc has also a bunch of other warnings, generally less useful. See http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Warning-Options.html#Warning-Options
It enables most warning messages.
You can find out more if you use g++ --help=warnings.
It enables all warnings. (reads as "Warning All")
It shows all warnings. I'd recommend also use -pedantic to warn about some non-conformant parts of code.

Best compiler warning level for C/C++ compilers? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
What compiler warning level do you recommend for different C/C++ compilers?
gcc and g++ will let you get away with a lot on the default level. I find the best warning level for me is '-Wall'. And I always try to remove fix the code for the warnings it generates. (Even the silly ones about using parenthesis for logical precedence rules or to say I really mean 'if (x = y)')
What are your favorite levels for the different compilers, such as Sun CC, aCC (HPUX ?), Visual Studio, intel?
Edit:
I just wanted to point out that I don't use "-Werror" (but I do understand it's utility) on gcc/g++ because, I use:
#warning "this is a note to myself"
in a few places in my code. Do all the compilers understand the #warning macro?
This is a set of extra-paranoid flags I'm using for C++ code:
-g -O -Wall -Weffc++ -pedantic \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wchar-subscripts -Wcomment -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat -Wformat=2 \
-Wformat-nonliteral -Wformat-security \
-Wformat-y2k \
-Wimplicit -Wimport -Winit-self -Winline \
-Winvalid-pch \
-Wunsafe-loop-optimizations -Wlong-long -Wmissing-braces \
-Wmissing-field-initializers -Wmissing-format-attribute \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked -Wpadded -Wparentheses -Wpointer-arith \
-Wredundant-decls -Wreturn-type \
-Wsequence-point -Wshadow -Wsign-compare -Wstack-protector \
-Wstrict-aliasing -Wstrict-aliasing=2 -Wswitch -Wswitch-default \
-Wswitch-enum -Wtrigraphs -Wuninitialized \
-Wunknown-pragmas -Wunreachable-code -Wunused \
-Wunused-function -Wunused-label -Wunused-parameter \
-Wunused-value -Wunused-variable -Wvariadic-macros \
-Wvolatile-register-var -Wwrite-strings
That should give you something to get started. Depending on a project, you might need to tone it down in order to not see warning coming from third-party libraries (which are usually pretty careless about being warning free.) For example, Boost vector/matrix code will make g++ emit a lot of noise.
A better way to handle such cases is to write a wrapper around g++ that still uses warnings tuned up to max but allows one to suppress them from being seen for specific files/line numbers. I wrote such a tool long time ago and will release it once I have time to clean it up.
On Visual C++, I use /W4 and /WX (treat warnings as errors).
VC also has /Wall, but it's incompatible with the standard headers.
I choose to treat warnings as errors, because that forces me to fix them. I fix all warnings, even if that means adding #pragma to ignore the warning - that way, I'm stating explicitly, that I'm aware of the warning (so other developers won't e-mail me about it).
I believe VC also supports
#pragma message ("note to self")
But as the system grows and grows, and you get a nightly build 30 developers work on simultaneously, it takes days to read all the notes to self, even in that amount that self is going to be do nothing but note reading and finally going to break under the stress not being able to keep up and have to resign...
No really, the amount of warnings is quickly going to grow if you allow them, and you won't be able to spot the really important ones (uninitialized variables, this pointer used in constructor, ...).
That's why I try to treat warnings as errors: most of the time, the compiler is right warning me, and if he isn't, I document it in the code and prepend
#pragma warning ( push )
#pragma warning ( 4191 : disable )
// violent code, properly documented
#pragma warning ( pop )
I just read they have a warning ( N : suppress ) pragma, too.
I tend to use -Wall (because everyone does make bugs, nobody is perfect) , but i don't use -Werror (treat warnings as errors) because now and then gcc warns about things which are right anyway (false positives).
I agree with litb to always use -Wall. In addition, if you want to ensure your code is compliant you can also use -pedantic. Another warning that can be helpful if you're handling unions and structs at the byte level is -Wpadded.
I do all development with Warning as Errors turned on.
Since I still develop in VC6 I have a lot of #pragma's in my code (4786 mainly).
There's a nice list of options for GCC here: http://mces.blogspot.com/2008/12/year-end-cleaning-ie-on-warning-options.htm.
-Wall does not enable all the possible warnings, and some have to be enabled explicitely.
I like -Wall and strict prototypes as well as implicit function definitions. Errors on those can be very useful. There's also -Wextra which will pick up all kinds of things like things you intended to be conditionals but accidentally wrote as statements:
if (something);
classic_way_to_leak_memory();
On Unix-like systems you have to obey the user's ENV preferences .. so what they see and report might be entirely different than what you need :)
I'm also a type punning fiend, so I tend to set -Fno-strict-aliasing as well, unless the user wants it. Safe memory management in classic C is hard to accomplish otherwise.
no one has mentioned the Intel compiler yet:
https://software.intel.com/sites/products/documentation/doclib/iss/2013/compiler/cpp-lin/GUID-D060680A-1A18-4574-8291-5C74E6E31335.htm
-w3 is pretty chatty, so I would suggest -w2
On GCC, for preference I use -Wall -Wextra -Wwrite-strings -Werror, and also specify a standard with std=. Which standard depends on the project: principally on how portable it needs to be.
The reason I use -Werror is that warnings are unacceptable (to me) even if they don't represent a real bug. I'd rather work around whatever caused the warning, than have to ignore warnings every single time I compile for the rest of my life. Once you allow warnings in the compile, it's just too easy to miss one that wasn't there last time.
Of course when dealing with third-party code, sometimes you can't get rid of the warnings. Then I'd decide on a case-by-case basis whether to relax the -W options, remove -Werror and write a script to check that only expect warnings occur, or maybe modify the third-party code (either to "fix" the warning or to disable it with pragmas if possible).
In Visual C I use /w3. I find w4 throws up too much noise (lots of it from the MS libraries) to go through on every build. The extra warnings are very minor and haven't been a cause of a bug so far.
I also like check all possible warnings that give compiler in my project. Unfortunately answer about Intel C++ compiler was not very informative for me (link is dead). I made my own research.
Because i use Qt 5 and qmake i have predefined warning level -w1. Can't do nothing with that. But this is not all and ICC has more keys:
-Wcomment
-Weffc++
-Wextra-tokens
-Wformat
-Winline // don't use, show only for example
-Wmain
-Wmissing-declarations
-Wmissing-prototypes
-Wnon-virtual-dtor
-Wp64
-Wpointer-arith
-Wremarks
-Wreturn-type
-Wsign-compare
-Wstrict-aliasing
-Wstrict-prototypes
-Wtrigraphs
-Wuninitialized
-Wunknown-pragmas
-Wunused-variable
More about all keys.
Also i want to add that, unlike GCC, ICC produces several warnings for one key, for example key -Weffc++. In case you want only see several warnings from all list use key -wd.
I disable: -wd1418,2012,2015,2017,2022,2013. And warnings -wd1572,873,2259,2261 was disabled in qmake by default.
I use PCH and have found very annoying to see in Qt Creator messages about using PCH file like error. To disable, use -Wno-pch-messages.
For disabling warning in code i use:
#if defined(Q_CC_INTEL)
#pragma warning( push )
#pragma warning( disable: 2021 )
#endif
// some code
#if defined(Q_CC_INTEL)
#pragma warning( pop )
#endif
Thanks everyone for their answers. It has been a while since I've used anything but gcc/g++. Ones I've had to use a long time ago are
-fmessage-length = 0 (since g++ had an ugly habit of line breaking messages)
-Wno-deprecated (since I worked on a code base pre-existing the std namespace)
I do remember that (at least 5 years ago) anything above the default warning level on the Sun Workshop CC compiler was too much. I also think this may have been true for the Intel compiler. I have not been up to date with non gnu compilers for a while.
The GCC compilers become stricter with every new version. Use the flag -ansi to produce warnings for violations of the strictest interpretation of the ANSI language standards. That's usually stuff that just happens to work in your current compiler, but may produce errors in the next version or in other compilers. That flag will help you avoid having to port your code every time you switch compilers/versions.