use cppcheck without defining all the macros - c++

I use cppcheck on a project using the boost library. The headers in this library contain a huge amount of macro that I don't even use in my sources. Nevertheless, cppcheck explore paths depending on these macros that I think useless. Is there a way to tell cppcheck to ignore all macros unless it's defined in a source code using a #define?

Here is the the necessary part from cppcheck documentation:
-D<ID> Define preprocessor symbol. Unless --max-configs or
--force is used, Cppcheck will only check the given
configuration when -D is used.
Example: '-DDEBUG=1 -D__cplusplus'.
-U<ID> Undefine preprocessor symbol. Use -U to explicitly
hide certain #ifdef <ID> code paths from checking.
Example: '-UDEBUG'
You are able to define (-D) or undefine (-U) custom preprocesser symbols with these options.
Another option that is potentially interesting is
-f, --force Force checking of all configurations in files. If used
together with '--max-configs=', the last option is the
one that is effective.
and
--max-configs=<limit>
Maximum number of configurations to check in a file
before skipping it. Default is '12'. If used together
with '--force', the last option is the one that is
effective.
This means the following:
cppcheck --force <PATH_TO_YOUR_CODE>
Cppcheck verifies all combinations of preprocessor paths, which could lead to long checking times on large code bases.
The corresponding documentation can be found here.

Not exactly what you want, but you can specify define to cppcheck so it evaluates only one branch:
see -D/-U options.

One option is to ignore lines with missing macros by putting this comment above the offending line:
// cppcheck-suppress unknownMacro

Use --config-exclude= to exclude the directories that contain unmanageable configurations. It only excludes header files.

Related

How to detect OS without directive ifdef?

I have to reset system date and time either on Linux, or on Windows.
How do I check OS without using ifdef, or if defined?
With CMake, you can conditionally add files to a target by using generator expressions. With that, you can isolate any platform-specific code in files, and use them in your build specification as follows.
add_executable(reset-time
$<$<PLATFORM_ID:Darwin>:resettime-macos.cpp>
$<$<PLATFORM_ID:Linux>:resettime-linux.cpp>
$<$<PLATFORM_ID:Windows>:resettime-windows.cpp>)
And as #eeroika pointed out in the comments, a good alternative is
add_executable(reset-time
resettime-$<LOWER_CASE:${CMAKE_SYSTEM_NAME}>.cpp)
as it requires not adjustment (of the CMakeLists.txt) when porting your project to a new system and you can catch a missing implementation file earlier, i.e., before linking.
You could set a global macro definition to the compiler based on which operating system you are compiling for. For example -D IS_WINDOWS=1. You could then use #if IS_WINDOWS instead of #ifdef. I don't know why this would be useful but it achieves what you asked.

Documenting preprocessor options with Doxygen

I have a C++ package that allows for different behavior if the user defines different pre-processor constants. For example, a user can use /D ALLOW_WIDE_CHAR in the makefile to change the behavior to support wide characters.
I would like to document these options with Doxygen, but Doxygen complains because there is no actual #define in the code. It is up to the user to do that.
Adding the definition to the PREDEFINED list in the configuration file doesn't help.
Suggestions?
One option I found is to create an extra source file, say Doxygen.h, that is not compiled, but is added to the Doxygen file list. This file can use #define to define those pre-processor constants. It seems like there should be a better solution, though.

c++ - #ifdef macro

I can see
#ifdef <token>
code;
#endif
to be included, but I can't find it defined in any of the headers it includes. Is there any other mechanism with which the token could be defined?
Firstly, there are macros that are implicitly defined by the compiler (for example, __cplusplus). Some of these are standard, and some are compiler-specific extensions. See your compiler manual for the full list.
Additionally, most compilers allow defining macros on the command line. The exact mechanism is compiler-dependent, but often takes the form of a -D or /D command-line option. For example, see the gcc manual:
-D name
Predefine name as a macro, with definition 1.
-D name=definition
The contents of definition are tokenized and processed as if they appeared during translation phase three in a `#define' directive. In particular, the definition will be truncated by embedded newline characters.
If you are invoking the preprocessor from a shell or shell-like program you may need to use the shell's quoting syntax to protect characters such as spaces that have a meaning in the shell syntax.
If you wish to define a function-like macro on the command line, write its argument list with surrounding parentheses before the equals sign (if any). Parentheses are meaningful to most shells, so you will need to quote the option. With sh and csh, -D'name(args...)=definition' works.
For Microsoft Visual C++, see http://msdn.microsoft.com/en-us/library/hhzbb5c8(v=vs.80).aspx
Some compilers provide convenient tools for figuring out where a particular preprocessor macro is defined. See, for example, How to know (in GCC) when given macro/preprocessor symbol gets declared?
Most (all?) compilers allow defining values with flags (-D in gcc), also some may be set by the compiler itself.
Yes, of course, preprocessor directives can be set with the compiler. For example, gcc lets you add directives in the command line, you can specify directives in the project settings in Visual Studio. Also think about __cplusplus, or _LINE_ of _FILE_. Those aren't defined anywhere, yet they exist. Also _DEBUG or UNICODE which are set up by the MSVS environment.

Getting only necessary headers out of boost

I need to submit an assignment, but I only want to include the header files from boost that I actually used (I made use of boost::shared_ptr and boost::function). I tried doing so manually, but I'm missing some header files and everytime i go to add them, it turns out I'm missing more. Is there a quick easy way to find out exactly what headers I actually need?
Thanks
The bcp command is made for this:
NAME
bcp - extract subsets of Boost
SYNOPSIS
bcp --list [options] module-list
bcp [options] module-list output-path
bcp --report [options] module-list html-file
bcp --help
DESCRIPTION
Copies all the files, including dependencies, found in module-list to
output-path. output-path must be an existing path.
But you will probably be surprised to see just how interdependent these Boost headers are.
There is a tool called bcp to do exactly that -- copy out the parts of Boost you need and no more.
There is actually another solution to your issue: the preprocessor.
The compiler you use should have a switch to only run the preprocessor: -E on gcc and clang. Given this, you can preprocess the two files you include, and stash the result of this run into a header file (each) of your own.
Add header guards, include the already preprocessed headers in lieu of the regular boost headers, and you're done.
Of course there might be some repetition between the two headers, a diff tool could potentially help you spotting it and factoring it in another common header... but for an assignment I would certainly not bother.
You might also consider telling your teacher that as he does not ask you to provide the standard library headers you compiled with, he should not be asking for the boost headers you used.

How can I get the compiler tell me what file #define a value?

My code is linking against several other libraries that are also developed at my company, one of these libraries is redefining several values from errno.h, I would like to be able to fix this, however I am having trouble finding the exact file that is redefining these values, I am want to know if there is a way to make the compiler tell me when a file has defined a particular value.
You can probably do it by adding -include errno.h to the command line that builds the library in question. Here's a quick example. I have a C program called "file.c":
#define ESRCH 8
That's it - then I compile with:
cc -c -include errno.h file.c
And presto, a compiler warning:
file.c:1:1: warning: "ESRCH" redefined
In file included from /usr/include/errno.h:23,
from <command-line>:0:
/usr/include/sys/errno.h:84:1: warning: this is the location of the previous definition
That will tell you where your bad definitions are.
Have you tried searching with grep?
If you don't want to search through all your headers for the particular #define, you could use
#undef YOUR_MANIFEST_CONSTANT
after each #include in your source module and then start removing them from the bottom up and see where your definitions come from.
Also, your compiler may tell you that a #define has been redefined. Turn all your warnings on.
With GCC I did something similar with:
g++ input.cc -dD -E > cpp.out
-dD tells cpp to print all defines where they were defined. And in the cpp output there are also markers for the include file names and the line numbers.
It is possible that some environments, I'm thinking IDE's here, have configuration options tied into the "project settings" rather than using a configuration header. If you work with a lot of other developers in a place where this behavior is NOT frowned on then you might also check your tool settings.
Most compilers will tell you where the problem is, you have to look and think about what the diagnostic notification is telling you.
Short of that, grep/findstr on *nix/Windows is your friend.
If that yields nothing then check for tool settings in your build system.
Some IDE's will jump to the correct location if you right click on the usage and select 'go to definition'.
Another option if you're really stuck is a command line option on the compiler. Most compilers have an option to output the assembler they generate when compiling C++ code.
You can view this assembler (which has comments letting you know the relative line number in the C++ source file). You don't have to understand the assembler but you can see what value was used and what files and definitions were included when the compiler ran. Check your compiler's documentation for the exact option to use