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.)
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)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
So, I think that's a good starting point. Didn't realize this was a dupe, but at least it was deeply buried. :-)
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 dounsigned short + (integral constant expression)
, that result is implicitly promoted to int. It then warns about a potential sign problem if you assign that value tounsigned
orunsigned 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 indefault: 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 othersPotentially 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 includeslong 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)
Try
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.