I have a big project that uses many, many libraries. Some of them are HDF5, PugiXML, Boost.ASIO, Qt, MuParser, and many others. Some of these libraries are included by header, and some are pre-compiled, and some of them I compiled myself. I'd like to use the gcc option -Weffc++ to ensure the quality of my code.
The problem is that I got over 2000 warnings when I enabled that option, and when I went quickly through the list, there was like 1 of them related to my project, and almost everything else was from the headers I included! It's very not practical to go through the whole list. Is there a way to tell gcc to either analyze files from given directories, or exclude directies in some way (regex maybe?).
The comments in the documentation are not good news:
When selecting this option, be aware that the standard library headers do not obey all of these guidelines; use ‘grep -v’ to filter out those warnings.
You can disable the warning temporarily with pragmas:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#include <header1>
#include <header2>
#pragma GCC diagnostic push
You might also be able to use -isystem to specify include paths, which suppresses certain warnings from files included through those paths.
Recommendation
Just don't use -Weffc++. It gives garbage even in your own project. For example, it will ask you to define virtual destructors for all base classes, regardless of whether that makes even a small amount of sense. It will warn if you don't initialize every member in aggregate initialization. After throwing my hands in the air and saying, "That warning is just stupid!" for the hundredth time, I turned -Weffc++ off and moved on with my life.
There are much better tools out there for code quality and enforcing style. Clang tools like clang-tidy, clang-modernize, and clang-format come to minde.
You can specify directories with -isystem to avoid the -Weffc++ processing on those directories. This works even when they have been specified earlier with -I.
Related
I'm working with a recent version of gcc, writing C++ code (but I would like an answer which would work for C as well). I have various extra warning flags enabled.
In my code, I am including a header from some popular library, #include <mylib.h>. Now, mylib.h triggers some of these compiler warnings; but I need to include it as-is, I can't alter it.
I want to suppress all compiler warnings when including mylib.h. I know I can suppress individual warnings with:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wwarning-name-here"
#pragma GCC diagnostic ignored "-Wanother-warning-name-here"
// my code goes here
#pragma GCC diagnostic pop
but I want to suppress all of the warnings. Can I do that? Note that I'm willing to tweak the compiler command-line if that helps.
Note: This related question indicates that, in 2015, one could not do this using pragmas.
From GCC manual:
2.7 System Headers
The header files declaring interfaces to the operating system and
runtime libraries often cannot be written in strictly conforming C.
Therefore, GCC gives code found in system headers special treatment.
All warnings, other than those generated by `#warning' (see
Diagnostics), are suppressed while GCC is processing a system header.
Macros defined in a system header are immune to a few warnings
wherever they are expanded. This immunity is granted on an ad-hoc
basis, when we find that a warning generates lots of false positives
because of code in macros defined in system headers.
Normally, only the headers found in specific directories are
considered system headers. These directories are determined when GCC
is compiled. There are, however, two ways to make normal headers into
system headers.
The -isystem command line option adds its argument to the list of
directories to search for headers, just like -I. Any headers found in
that directory will be considered system headers.
All directories named by -isystem are searched after all directories
named by -I, no matter what their order was on the command line. If
the same directory is named by both -I and -isystem, the -I option is
ignored. GCC provides an informative message when this occurs if -v is
used.
There is also a directive, #pragma GCC system_header, which tells GCC
to consider the rest of the current include file a system header, no
matter where it was found. Code that comes before the `#pragma' in the
file will not be affected. #pragma GCC system_header has no effect in
the primary source file.
how to make this happen in CMake?
From CMake manual:
include_directories
Add include directories to the build.
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
...
If the SYSTEM option is given, the compiler will be told the directories are meant as system include directories on some platforms. Signalling this setting might achieve effects such as the compiler skipping warnings, or these fixed-install system files not being considered in dependency calculations - see compiler docs.
I am integrating Guideline Support Library Checkers into a project of mine.
Microsoft.CppCoreCheck
Microsoft.Gsl
When I run it I get a bunch of errors from included libraries like standard libraries, glm, boost, etc.
One concrete example is SDL.h where I get warnings in sdl_stdinc.h.
I made sure that I include SDL only via one header under my control:
ExtSDL.hpp
#pragma once
#pragma warning(disable: 4710)
#pragma warning(push, 0)
#include <SDL.h>
#pragma warning(pop)
I can not find information on how to exclude this library from the static code analysis.
There are multiple ways to suppress CppCoreCheck warnings:
you can suppress CppCoreChecks either using
[[gsl::suppress(chapter)]] attribute, where chapter comes from C++
Core Guidelines, for example, con.4. Please also look at MS docs for information.
you can use #pragma warning to suppress warnings individually or in bulk, as mentioend above.
you can suppress all warnings for "not your code" using CAExcludePath.
The most practical approach I've found so far is to build up #defines like
#define SDL_WARNINGS 4710 26135
and then #include other people's dirty code thusly
#pragma warning(push)
#pragma warning(disable: SDL_WARNINGS)
#include <SDL.h>
#pragma warning(pop)
That will silence warnings for gsl checkers, based on their associated warning codes e.g C26135 above. It silences the compiler exactly where you want it to keep quiet. Note the warning disablement is local to the push/pop scope.
This sort of approach allows one to compile /Wall /WX even if you turn additional checking on, including gsl. Critically it works even when you have dependencies on other people's headers which aren't warning clean. Sadly this includes every C and C++ standard library implementation I've seen plus Boost, LLVM, the Windows SDK etc. etc. i.e. basically everything. Additionally it protects you from evil headers which alter warning pragmas (some standard library implementations used to do this and may still...) This approach allows you to lift your own code to a higher level of cleanliness and quality than the dross you are dependent upon.
One of the good things about the Microsoft C++ Core Check stuff is the way they've tied it into the usual mechanisms used for warnings, so this approach works uniformly for regular warnings and checkers in extra rulesets. Thank goodness they did something like this: some of the gsl checkers are rather questionable and incompatible with many extant coding styles i.e. turn gsl on for code which #includes big standard vendor library and you rapidly need to construct a long list of warning codes to disable before you can dial the noise down so you can focus on your own code. Of course you can globally #pragma warning(disable: GSL_CHECKERS_YOU_DONT_LIKE) for your own code, so you can focus on the aspects of it you find useful.
Alternatively you can pick the rules to apply by selecting rulesets to use and/or making a custom one. That's presumably going to minimise your build times which aren't as quick with Code Analysis enabled.
It would be nice to have a more direct answer to your question which essentially made the dirty headers build quickly because you could disable checkers for "other people's stuff". It's an obvious feature request but I'm not aware of it being supported. Presumably it would be pretty trivial to implement e.g. only run the checkers on source code found in a specified set of directories, so if a #include steps outside that zone the checkers are automatically disabled. Is anyone at Microsoft reading this?
I had to customize some projects which have been written for some other purpose but some core functionality is same for my project and works as it is. But There are lots of variables, macros,functions etc.. which are not useful for my current context and they are just making the code very uneasy to read and unnecessarily big.
So I started removing the variables macros functions etc.. by using "Find References" and "Show Call Graph" in Netbeans. I'm using netbeans remote development tools for c/c++.
But its cumbersome. So Is there any tool to do this clean up??
From what I know there is currently no tool that does all the things you have mentioned, however there is one that helps in cleaning up the unused include headers: include-what-you-use
"Include what you use" means this: for every symbol (type, function
variable, or macro) that you use in foo.cc, either foo.cc or foo.h
should #include a .h file that exports the declaration of that symbol.
The include-what-you-use tool is a program that can be built with the
clang libraries in order to analyze #includes of source files to find
include-what-you-use violations, and suggest fixes for them.
The main goal of include-what-you-use is to remove superfluous #includes. It does this both by figuring out what #includes are not actually needed for this file (for both .cc and .h files), and
replacing #includes with forward-declares when possible.
One might expect that the Clang static analyzer would do this, but from what I see the availalbe checks do not offer such things.
This might be a good time for someone to suggest a feature request to the analyzer or create a separate tool using LibTooling on a similar par with the tools described at Clang Tools
In the meantime, I'd suggest you enable -Wall and -Wextra compiler flags, which will trigger the following warnings (among others)(see the GCC docs below):
-Wunused-function
-Wunused-label
-Wunused-value
-Wunused-variable
-Wunused-parameter
-Wunused-but-set-parameter
If for some reason you don't want to do that, you could just add -Wunused which will enable only the above -Wunused options combined, without the other flags that -Wall or -Wextra adds.
But in order to get a warning about an unused function parameter, you
must either specify -Wextra -Wunused (note that -Wall implies
-Wunused), or separately specify -Wunused-parameter.
Of course, this means that you have to do the cleanup manually
If you want to be extra pedantic you might as well convert all the warnings into errors by adding the -pedantic-errors flag
For more details read the GCC Warnings Options documentation.
I've sometimes used the method of marking a big block of code as "not used" by adding
#if 0
... lots of code
#endif
You can then compile the code and see what goes wrong. Analyze the "undeclared varibale X" errors you get and reinstate the bits necessary for that. You can do this by either "cutting up" the #if 0 block (adding an #endif, then a new #if 0 a bit further down), or by moving the pieces you need out of the current block.
For example, if you have a block of global variables or macros, just put #if 0 around all of them, and see which ones are actually used. [Although macros can be a little more tricky if they are used in #ifdef and such].
I'd be surprised if there isn't a tool out there, but at the same time, you still have to do the cutting job, and once you have a large chunk of code in #if 0 ... #endif, it's pretty easy to cut it out.
Many static code analysis tools provide the information you want. Wikipedia has a list.
We have successfully used such a tool (with some custom changes) to remove includes and speed up compile time.
Is it possible to restict the -pedantic switch for certain files? For example I compile stuff using alsa-lib, which I refer with standard
#include <alsa/asoundlib.h>
however -pedantic panics on this file. I am willing and interested in correcting warning and oddities in my own code, but not in alsa and other unrelated third parties.
Is there a way to scope the -pedantic usage?
Normally, GCC suppresses warnings in system headers, unless you explicitly specify -Wsystem-headers. And normally, files included with <> from /usr/include are treated as system headers. Your question suggests you specifically added something that makes GCC not treat it as a system header. You haven't specified which compiler options you're using, but are you adding any pointless -I* options that might make /usr/include get treated as a non-system header directory?
If all else fails, you can use the -isystem to actually add directories as system header directories, but you shouldn't need that here.
Edit: after re-reading the question, if you installed alsa-lib in a non-standard path, then my remark that you should not need the -isystem option may be wrong: it may be exactly what you need.
You can scope any compilation key to one compilation unit.
Apperently, if you has multiple compilation units you can use deferent keys to compile them:
g++ -pedantic file_that_does_not_use_ugly_alsa.cpp
g++ file_that_uses_ugly_alsa.cpp
But you you can not scope keys inside compilation unit: code get prepropcessed before compiling, all headers are inlined and actually after macros substitution you may find out that your code uses some things, that make compiler panic.
I have a project that uses log4cxx, boost, etc. libraries whose headers generate lots of (repetitive) warnings. Is there a way to suppress warnings from library includes (i.e. #include <some-header.h>) or includes from certain paths? I'd like to use -Wall and/or -Wextra as usual on project code without relevant info being obscured. I currently use grep on make output but I'd like something better.
You may try to include library headers using -isystem instead of -I. This will make them "system headers" and GCC won't report warnings for them.
For those using CMake, you can modify your include_directories directives to include the symbol SYSTEM which suppresses warnings against such headers.
include_directories(SYSTEM "${LIB_DIR}/Include")
^^^^^^
You can use pragmas. For example:
// save diagnostic state
#pragma GCC diagnostic push
// turn off the specific warning. Can also use "-Wall"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/lexical_cast.hpp>
// turn the warnings back on
#pragma GCC diagnostic pop
I found the trick. For library includes, instead of -Idir use -isystem dir in the makefile. GCC then treats boost etc. as system includes and ignores any warnings from them.
#pragma are instructions to the compiler. you can set something before the #include and disable it after.
You can also do it at the command line.
Another GCC page specifically on disabling warnings.
I would go for the option of using #pragma's within the source code, and then providing a
sound reason (as a comment) of why you are disabling the warnings. This would mean reasoning about the headers files.
GCC approaches this by classifying the warning types. You can classify them to be warnings or to be ignored. The previously linked articles will show you which warnings are may be disabled.
Note: you can also massage the source code to prevent certain warnings by using attributes; however, this bind you quite closely to GCC.
Note2: GCC also uses the pop/push interface as used in microsoft's compiler -- Microsoft disables warnings through this interface. I suggest you investigate this further , as I do not know if it is even possible.
Putting the following
#pragma GCC system_header
will turn off GCC warnings for all following code in this file.
You can try using precompiled headers. Warnings won't go away but at least the won't show up in your main compilation.
If you need to explicitly override a system header then you're restricted to pragmas. You can verify which includes you're using via make depend output.
Also see diagnostic push-pop for gcc >= 4.6
Another way to do it is, in the makefile, to tell the compiler to ignore warnings for the specific folder:
$(BUILD_DIR)/libs/%.c.o: CFLAGS += -w
There must be reasons for those warnings. These will either be caused by errors in your code that uses the library, or by errors in the library code itself. In the first case, fix your code. In the second case, either stop using the library or if it is FOSS code, fix it.