Flags to enable thorough and verbose g++ warnings
Asked Answered
G

4

141

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.)

Galvanoscope answered 23/2, 2011 at 8:20 Comment(6)
What gcc needs (since it's decided to blatantly lie about -Wall) is a -Wbloody_everything flag :-)Nerty
You may mark your question as a dupe but you may also put your last edit as an answer since you actually answered your question. And I would be glad to upvote it then :)Administrative
Oh, good idea! Can't accept for 2 days, but maybe someone else will come up with additional flags in the interim.Galvanoscope
OP and @paxdiablo: GCC has consistently rejected this sort of thing, but it's available in Clang via -Weverything. I've read that even the Clang++ developers are a little concerned about users turning it on; apparently it was intended for internal development use only. This makes no sense, though, because turning on -Weverything is probably the best possible way to discover potentially helpful warnings that you didn't know about before.Wareing
OP and @Nerty There's now a way to figure out the complete list of warnings for a given GCC version: github.com/barro/compiler-warningsWareing
Possible duplicate of How to turn on (literally) ALL of GCC's warnings?Birdman
G
45

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. :-)

Galvanoscope answered 23/2, 2011 at 8:38 Comment(6)
Perhaps, but that seems to change between versions, and likely at the whim of sun spots and RMS, so being overly-explicit probably won't hurt. It's a good starting point, anyway.Galvanoscope
From a quick grep of 4.5.2's c-opts.c/opts.c for 'case OPT_W', you're missing: strict overflow, undef, strict nul sentinel, normalized, multichar, implicit function declaration, deprecated, endif labels, comments, builtin macro redefined, larger than, larger than eq, abi. It is crazy that there's not a command line option to list them.Saida
I think it's crazier that -Wall doesn't do what one would expect it to. But thank you, some of those look very useful!Galvanoscope
Disabling warnings has its place. After all, they are "warnings". Another situation is when you enable a flag that enables multiple warnings, but you want to be selective about it.Lockhart
@Administrative That's a very good idea, I cross checked with the documentation.Chappy
How are you able to use -Waggregate-return? This gives me a warning for every use of begin/end()Mcmaster
E
160

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)

Extramarital answered 25/3, 2012 at 18:28 Comment(12)
I recently submitted an enhancement request based on my research for this answer: gcc.gnu.org/bugzilla/show_bug.cgi?id=53313. It would dramatically simplify the warning situation by creating warning levels. In my proposal, my suggested set of warnings is approximately -W4, with an additional proposal to create -Winf, which would mean -Weverything-and-I-really-mean-it-this-timeExtramarital
Enhancement request that would cause part of -Wpadded be added to the recommended list: gcc.gnu.org/bugzilla/show_bug.cgi?id=53514Extramarital
Enhancement request that would cause parts of -Weffc++ to be added to the recommended list: gcc.gnu.org/bugzilla/show_bug.cgi?id=16166Extramarital
I don't really understand your argumentation about -Wswitch-enum isn't just writing perhaps doing nothing default: branch technically disables warning from specific switch?Radiochemistry
@Predelnik: It's trickier than that. -Wswitch-enum warns if you do not explicitly handle every enumeration value in a switch, and default does not count as explicit. On the other hand, -Wswitch-default warns you if your switch does not have a default case, even if you have explicitly covered all possible values.Extramarital
This list is awesome. FYI, someone has now written an automated tool to find all warnings for a given version of GCC or Clang, and has published these lists for many compiler versions; see here: github.com/barro/compiler-warningsWareing
I suggest to add -Wnon-virtual-dtor, which nowadays is activated with -Weffc++ but comes without the potential issues of -Weffc++ .Peake
BTW - use -isystem instead of -I on your "old library code" to prevent all those false positivesMadra
-Wfloat-equal isn't actually in your list in this answer.Charpoy
-Wstrict-overflow=5 is acutally VERY questionable. Even the manual mentions that this generates lots of false positives.Mcmaster
Flamefire, you are correct. I have found that values greater than -Wstrict-overflow=2 tend to be too noisy to be useful.Extramarital
Please delete -Werror - at least from the upper command-line. It might be advisable to use it, but - it doesn't add warnings, and that's what OP had asked about.Paleontography
G
45

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. :-)

Galvanoscope answered 23/2, 2011 at 8:38 Comment(6)
Perhaps, but that seems to change between versions, and likely at the whim of sun spots and RMS, so being overly-explicit probably won't hurt. It's a good starting point, anyway.Galvanoscope
From a quick grep of 4.5.2's c-opts.c/opts.c for 'case OPT_W', you're missing: strict overflow, undef, strict nul sentinel, normalized, multichar, implicit function declaration, deprecated, endif labels, comments, builtin macro redefined, larger than, larger than eq, abi. It is crazy that there's not a command line option to list them.Saida
I think it's crazier that -Wall doesn't do what one would expect it to. But thank you, some of those look very useful!Galvanoscope
Disabling warnings has its place. After all, they are "warnings". Another situation is when you enable a flag that enables multiple warnings, but you want to be selective about it.Lockhart
@Administrative That's a very good idea, I cross checked with the documentation.Chappy
How are you able to use -Waggregate-return? This gives me a warning for every use of begin/end()Mcmaster
P
17

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)

Pickle answered 23/2, 2011 at 8:52 Comment(2)
-Werror can be disabled for specific types of warnings, for example: -Werror -Weffc++ -Wno-error=effc++Trainband
ansi: In C mode, this is equivalent to -std=c89. In C++ mode, it is equivalent to -std=c++98. i.e. if youre specifying some other std, dont use ansiMysterious
R
2

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.

Rockies answered 2/4, 2013 at 18:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.