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.
Related
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>:
...
>
)
I'd like to know what switch you pass to the gcc compiler to turn off unused variable warnings? I'm getting errors out of boost on windows and I do not want to touch the boost code:
C:\boost_1_52_0/boost/system/error_code.hpp: At global scope:
C:\boost_1_52_0/boost/system/error_code.hpp:214:36: error: 'boost::system::posix_category' defined but not used [-Werror=unused-variable]
C:\boost_1_52_0/boost/system/error_code.hpp:215:36: error: 'boost::system::errno_ecat' defined but not used [-Werror=unused-variable]
C:\boost_1_52_0/boost/system/error_code.hpp:216:36: error: 'boost::system::native_ecat' defined but not used [-Werror=unused-variable]
I tried using both -Wunused-value and -Wno-unused-value but neither suppressed the messages above.
What is the right command, here is my compile line:
g++ -g -fno-inline -Wall -Werror -Wextra -Wfloat-equal -Wshadow
-Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wno-conversion
-Wdisabled-optimization -Wredundant-decls -Wunused-value -Wno-deprecated
-IC:\\boost_1_52_0 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-c -o op.o op.cpp
Perhaps the -Wall overrides my goal?
The -Wno-unused-variable switch usually does the trick. However, that is a very useful warning indeed if you care about these things in your project. It becomes annoying when GCC starts to warn you about things not in your code though.
I would recommend you keeping the warning on, but use -isystem instead of -I for include directories of third-party projects. That flag tells GCC not to warn you about the stuff you have no control over.
For example, instead of -IC:\\boost_1_52_0, say -isystem C:\\boost_1_52_0.
Sometimes you just need to suppress only some warnings and you want to keep other warnings, just to be safe. In your code, you can suppress the warnings for variables and even formal parameters by using GCC's unused attribute. Lets say you have this code snippet:
void func(unsigned number, const int version)
{
unsigned tmp;
std::cout << number << std::endl;
}
There might be a situation, when you need to use this function as a handler - which (imho) is quite common in C++ Boost library. Then you need the second formal parameter version, so the function's signature is the same as the template the handler requires, otherwise the compilation would fail. But you don't really need it in the function itself either...
The solution how to mark variable or the formal parameter to be excluded from warnings is this:
void func(unsigned number, const int version __attribute__((unused)))
{
unsigned tmp __attribute__((unused));
std::cout << number << std::endl;
}
GCC has many other parameters, you can check them in the man pages. This also works for the C programs, not only C++, and I think it can be used in almost every function, not just handlers. Go ahead and try it! ;)
P.S.: Lately I used this to suppress warnings of Boosts' serialization in template like this:
template <typename Archive>
void serialize(Archive &ar, const unsigned int version __attribute__((unused)))
EDIT: Apparently, I didn't answer your question as you needed, drak0sha done it better. It's because I mainly followed the title of the question, my bad. Hopefully, this might help other people, who get here because of that title... :)
If you're using gcc and want to disable the warning for selected code, you can use the #pragma compiler directive:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
( your problematic library includes )
#pragma GCC diagnostic pop
For code you control, you may also use __attribute__((unused)) to instruct the compiler that specific variables are not used.
See man gcc under Warning Options. There you have a whole bunch of unused
Warning Options
... -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable
If you prefix any of them with no-, it will disable this warning.
Many options have long names starting with -f or with -W---for example, -fmove-loop-invariants, -Wformat and so on. Most of these have both positive and negative forms; the negative form of -ffoo would be -fno-foo. This manual documents only one of these two forms, whichever one is not the default.
More detailed explanation can be found at Options to Request or Suppress Warnings
Use -Wno-unused-variable should work.
You can prefix the variables with '(void)'.
This can be useful if you don't have access to the build framework or you only want to affect a local change in behavior.
IE:
int main()
{
int unused1; //This will print warning
int unused2; //This will not print warning -
// |
(void) unused2; // <----------------------------
}
Output:
$ g++ -Wall test.cc
test.cc: In function ‘int main()’:
test.cc:4:7: warning: unused variable ‘unused1’ [-Wunused-variable]
4 | int unused1;
| ^~~~~~~
How do you disable the unused variable warnings coming out of gcc?
I'm getting errors out of boost on windows and I do not want to touch the boost code...
You visit Boost's Trac and file a bug report against Boost.
Your application is not responsible for clearing library warnings and errors. The library is responsible for clearing its own warnings and errors.
The compiler is already telling you, it's not value but variable. You are looking for -Wno-unused-variable. Also, try g++ --help=warnings to see a list of available options.
-Wall and -Wextra sets the stage in GCC and the subsequent -Wno-unused-variable may not take effect. For example, if you have:
CFLAGS += -std=c99 -pedantic -pedantic-errors -Werror -g0 -Os \
-fno-strict-overflow -fno-strict-aliasing \
-Wall -Wextra \
-pthread \
-Wno-unused-label \
-Wno-unused-function \
-Wno-unused-parameter \
-Wno-unused-variable \
$(INC)
then GCC sees the instruction -Wall -Wextra and seems to ignore -Wno-unused-variable
This can instead look like this below and you get the desired effect of not being stopped in your compile on the unused variable:
CFLAGS += -std=c99 -pedantic -pedantic-errors -Werror -g0 -Os \
-fno-strict-overflow -fno-strict-aliasing \
-pthread \
-Wno-unused-label \
-Wno-unused-function \
$(INC)
There is a good reason it is called a "warning" vs an "error". Failing the compile just because you code is not complete (say you are stubbing the algorithm out) can be defeating.
I recommend neither editing 3rd party code nor suppressing warnings globally. If you are using CMake, you can suppress specific warning only for the external library.
find_package(Boost REQUIRED)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
target_compile_options(Boost::boost PUBLIC -Wno-unused-variable)
endif()
...
add_executable(main "main.cpp")
target_link_libraries(main Boost::boost)
See also FindBoost.cmake.
I was looking for a list of recommended g++ warning options for C++ and only could find this: Recommended gcc warning options for C and Useful GCC flags for C which are all quite C specific
-Wall and -Wextra enable most but not all of the warnings gcc can generate.
Which warnings that aren't enabled by those options especially when compiling C++ should be turned on as well?
-Wall -Wextra tends to cover the really noteworthy ones. Personally, I also like to compile with -ansi -pedantic and occasionally -Wshadow.
Also, it can be a little noisy and not useful 100% of the time, but -Weffc++ sometimes has good suggestions for better code quality as well.
EDIT In the age of modern C++, you should replace -ansi -pedantic with -std=c++14 -pedantic or whatever your version of choice is, since -ansi will put the compiler into C++98/C++-03 mode.
Don't forget -Wstrict-aliasing.
I found this post was good, look the params up:
Recommended gcc warning options for C
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)
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/