Being extremely pedantic with the way your code is compiled - c++

I would like to find out which is the most extreme error checking flag combination for g++ (4.7). We are not using the new C++11 specification, since we need to cross compile the code with older compilers, and these older compilers (mostly g++ 4.0) often cause problems which simply are ignored by the g++4.7.
Right now we use the following set of flags:
-Wall -Wcomment -Wformat -Winit-self -ansi -pedantic-errors \
-Wno-long-long -Wmissing-include-dirs -Werror -Wextra
but this combination does not identify issues such as a double being passed in to a function which expects int, or comparison between signed and unsigned int and this causes the old compiler to choke on it.
I have read through the documentation and -Wsign-compare should be enabled by -Wextra but in practice seems this is not the case, so I might have missed something...

The -ansi is alias for the default standard without GNU extensions. I'd suggest instead being explicit using -std=c++98, but it should be default for g++ -ansi, so not really different.
But generally I've never seen anything that would be accepted by newer gcc and rejected by older gcc on the grounds of being invalid. I suspect any such problem is a bug in the older compiler or it's standard library. Gcc does not have warnings for things that are correct, but didn't work with older versions of it, so you don't have any other option than to test with the older version.
As for the specific issues you mention:
Passing double to function that expects int is not an error. It might be undefined behaviour though. -Wconversion should help.
Comparing signed with unsigned is also well defined, also always worked as defined and in case of equality comparisons actually makes programmers write worse code (comparing unsigned variable larger than int with -1 is something else than comparing it with -1u). So I actually always compile with -Wno-sign-compare.
The compiler should not print warnings for headers found in directories given with -isystem instead of -I, so that should let you silence the warning for Qt headers and keep it enabled for your own code. So you should be able to use -Wconversion.

Use lint or some other static analysis tool to check the code, in addition to compiler. On my Linux distro, apt-get install splint will get splint, maybe check if that has been packaged for your OS for easy installation.

Related

g++ arm-none-eabi upgrade from 4.9 to gcc 8.2. Generated binary do not fit any more in flash

I recently updated my Linux laptop from Ubuntu 16.04 to 18.04.
I had a STM32 (Cortex-M4) Makefile based project that compiled correctly with the arm-none-eabi g++ version provided by Ubuntu. The generated file required 47620 bytes in the .text section.
With the Ubuntu upgrade, I have also installed an up-to-date version of gcc (from ARM website). Version is 8.2.1.
When I compile the same project (make clean && make), the generated binary do not fit in flash (97424 bytes required, more than twice!). The project is exactly the same (sources, link script, startup files, Makefile).
The compiler options are: -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -DSTM32F303x8 -DARMCM4 -O0 -g -Wall -fexceptions -Wno-deprecated.
The linker options are -mthumb -mcpu=cortex-m4 -Tstm32f303K8.ld -mfloat-abi=hard -mfpu=fpv4-sp-d16 --specs=nosys.specs -lm -Wl,--start-group -lm -Wl,--end-group -Wl,--gc-sections -Lsys -Xlinker -Map=test.elf.map
When I look at the .Map generated file, all the user functions take approximatively the same size (new version saves 8 bytes!). But after, it includes C++ sepcific parts, and one is more than 26Kb (from map file):
.text 0x00000000080079e8 0x683c /usr/local/gcc-arm-none-eabi-8-2018-q4-major/bin/../lib/gcc/arm-none-eabi/8.2.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libstdc++.a(cp-demangle.o)
0x000000000800e13c __cxa_demangle
Note: there is no problem with C only projects, only with C++. The library included are the same (gcc 4.9.3 -> armv7e-m/fpu, and gcc 8.2.1 -> thumb/v7e-m+fp/hard):
libm.a libstdc++.a libc.a libnosys.a libgcc.a
Is there a way to get rid of that so that I can compile and flash my (no so old) project?
regards,
I found a solution using the libstdc++_nano (instead of implicit libstc++). With that, the code size is reduced from 84kb to 26kb!
LDFLAGS += -lstdc++_nano
It just works. Thanks #Henrik, #Matthieu and #EOF for your support!
It might be related to exception handling, as std::terminate(), which is used with exceptions, might call the demangling routine. If you don't need exceptions then try disabling them with -fno-exceptions as described here.
Another solution might be to look at the GCC headers:
Demangling routine.
ABI-mandated entry point in the C++ runtime library for demangling.
[...]
returns a pointer to the start of the NUL-terminated demangled
name, or NULL if the demangling fails. The caller is
responsible for deallocating this memory using free.
The prototype is:
char*
__cxa_demangle(const char* __mangled_name, char* __output_buffer,
size_t* __length, int* __status);
So you could probably just supply your own dummy function returning NULL (Given that all library functions are weak, and can be overridden). I'll advise you to look at the disassembled code first though, and find out how and why it is being called in the first place, since it might change behaviour to just discard functionality).
They also give other advise in This forum post, which might be useful for you as well:
Optimize for size with -Os instead of -O0 (possibly add the -Og option instead, if you prefer easily debuggable code, it is often both smaller and faster than -O0).
Optimize at link-time with -flto while compiling and linking.
Maybe disable RTTI if not used.

Intel Pin with C++14

The Questions
I have a few questions surrounding usage of Intel Pin with C++14 or other C++ verions.
There are rarely any problems compiling code from older C++ with newer versions, but since Intel Pin is manipulates instruction level, is there any undesirable side effects that might come if I compile it with C++11 or C++14?
If it's ok to compile with C++11 or C++14, how do I make a rule to enable a newer version of C++ for my tool only?
How do I set GCC/G++ default C++ version to latest, if possible, and what should I keep in mind when doing so?
Situation
I'm building a dynamic call graph pin tool. To make it understandable, I'm computing the depth of the call stack. For safety, I decided to wrap the excerpt of code that increments or decrements the depth with a std::mutex. This has gotten me to the problem that std::mutex is available only since C++11, which is not Intel Pin default in my machine.
$ g++ -v
[...]
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.2)
Compile command:
$ make obj-intel64/callgraph.so
[...]
error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
#error This file requires compiler and library support
[...]
EDIT
I managed to make a build rule that defines version to C++11, but it breaks. The command sent to g++ through make was
g++ -DBIGARRAY_MULTIPLIER=1 -Wall -Werror -Wno-unknown-pragmas -D__PIN__=1
-DPIN_CRT=1 -fno-stack-protector -fno-exceptions -funwind-tables
-fasynchronous-unwind-tables -fno-rtti -DTARGET_IA32E -DHOST_IA32E -fPIC
-DTARGET_LINUX -fabi-version=2 -I/home/gabriel/Downloads/pin-3.0-76991-gcc-linux/source/include/pin
-I/home/gabriel/Downloads/pin-3.0-76991-gcc-linux/source/include/pin/gen
-isystem /home/gabriel/Downloads/pin-3.0-76991-gcc-linux/extras/stlport/include
-isystem /home/gabriel/Downloads/pin-3.0-76991-gcc-linux/extras/libstdc++/include
-isystem /home/gabriel/Downloads/pin-3.0-76991-gcc-linux/extras/crt/include
-isystem /home/gabriel/Downloads/pin-3.0-76991-gcc-linux/extras/crt/include/arch-x86_64
-isystem /home/gabriel/Downloads/pin-3.0-76991-gcc-linux/extras/crt/include/kernel/uapi
-isystem /home/gabriel/Downloads/pin-3.0-76991-gcc-linux/extras/crt/include/kernel/uapi/asm-x86
-I/home/gabriel/Downloads/pin-3.0-76991-gcc-linux/extras/components/include
-I/home/gabriel/Downloads/pin-3.0-76991-gcc-linux/extras/xed-intel64/include
-I/home/gabriel/Downloads/pin-3.0-76991-gcc-linux/source/tools/InstLib -O3
-fomit-frame-pointer -fno-strict-aliasing -std=c++11
-c -o obj-intel64/callgraph.o callgraph.cpp
This doesn't compile. Instead, it'll fall into a huge error log inside STL headers. It appears that Pin comes along with it's own subset of STL, that conflicts with C++11 and C++14. I've uploaded a paste of the g++ output. It filled 2331 lines, but I've noticed that strange thing in the folders it visits. STL libraries are included from 2 different directories:
/usr/include/c++/5/
/home/gabriel/Downloads/pin-3.0-76991-gcc-linux/extras/stlport/include/
Solving errors one-by-one is unfeasible, deleting pin stl port probably is an even worse idea. If it's possible to use Pin with newer C++, I'd say simple std=c++1y is not the way.
From the compiler options used to compile the pin tool, I presume you are using the latest version of Pin, namely 3.0. According to Intel, the CRT that ships with the framework doesn't support C++11 and later versions of the language. In particular, you will not be able to use any of the APIs supported in C++11 including std::mutex. If it's critical for you to use C++11 APIs then you should use the previous version of Pin, namely 2.14, which doesn't ship with a CRT and uses the CRT of your compiler.
However, if all you want is a mutex, you can use the OS-portable mutex that ships with Pin 3.0. For more information, refer to the documentation.
When using Pin 3.0 you are not allowed to use any header file or object file of your compiler (those from /usr/include/c++/5/). You can only use PinCRT and few system header files.

Caught set but unused parameters with clang

Is there a way I could catch set but unused variables using clang, something similar to gcc's Werror=unused-but-set-parameter?
I set -Wunused but clang doesn't catch set but unused parameters.
I am not sure if you have tried more than what you have listed, but here is more information on CLANG unused options, using its GCC compatibility:
First, here is what the documentation suggests:
-Wextra -Wunused-but-set-parameter
The following is background reference information:
From HERE:
If you are using the LLVM-GCC or Apple LLVM Compiler build option there are a large number of possible compiler warnings that you can enable/disable. The Clang front end also supports the GCC diagnostic warnings (see http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html) for backwards compatibility.
Following the referenced link in that quote lists several unused options from the GCC family of warnings:
-Wall
This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. This also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.
-Wall turns on the following warning flags:
(there are many more, just listing 'unused')
...
-Wunused-function
-Wunused-label
-Wunused-value
-Wunused-variable
...
And finally, just below the last block:
-Wextra
This enables some extra warning flags that are not enabled by -Wall.
(This option used to be called -W. The older name is still supported, but the newer name is more descriptive.)
(again, there are more, just listing _unused variety)
-Wunused-parameter (only with -Wunused or -Wall)
-Wunused-but-set-parameter (only with -Wunused or -Wall)
There is an equivalent warning generated by clang-tidy, integrated from clang-analyzer:
note: Value stored to 'tmp' is never read
warning: Value stored to 'tmp' is never read [clang-analyzer-deadcode.DeadStores]
It looks like LLVM chose to implement some of the GCC warnings as separate tools.
In this website, if you search for 'unused' you can find some flags that you could use. And I think this one is your flag:
clang -Wunused-variable test.c

Set of Warnings as Error g++

I want to change the behavior of warnings and errors for my g++ compiler:
I want that normal warnings are spotted as errors (-Werror)
I want extra warnings to be spotted. (-Wall and -Wextra)
But my problem is that this way, all and extra warning are made errors. Is there a way to achieve what I want without needing to set a long list at -Werror=xxx,xxx,xxx. Is there some kind of alias for set of errors?
If you just give -Werror all warnings become errors. Aside from listing the ones you (don't) want to make into errors as -W(no-)error=xxx, I don't believe there is a way to "make some warnings into errors".
Of course, one solution might be to compile the code twice - once with -Wall and -Wextra, and once with -Werror, but not -Wall and -Wextra.
In the long term, I'm sure it will be worth the extra effort of marking which errors you (don't) want -Werror to see as errors [although I'd say the better solution is probably to use -Wno-xxx, to disable any warnings that you deem acceptable, as opposed to "warn but don't make it an error" - after all, the purpose of -Werror in my view is to prevent code from being submitted to a project with warnings in it - and that should mean one of two things: the warning is fixed, or the warning is disabled. Whichever makes sense for that project].
Rather than using -Werror=... with a long list of warnings you can use -Werror -Wno-error=... with a much shorter list of warnings (only the ones enabled by -Wall -Wextra). The manual lists which warnings are enabled by -Wall -Wextra so it's a no-brainer.

What extra optimisation does g++ do with -Ofast?

In g++ 4.6 (or later), what extra optimisations does -Ofast enable other than -ffast-math?
The man page says this option "also enables optimizations that are not valid for all standard compliant programs". Where can I find more information about whether this might affect my program or not?
Here's a command for checking what options are enabled with -Ofast:
$ g++ -c -Q -Ofast --help=optimizers | grep enabled
Since I only have g++ 4.4 that doesn't support -Ofast, I can't show you the output.
The -Ofast options might silently enable the gcc C++ extensions. You should check your sources to see if you make any use of them. In addition, the compiler might turn off some obscure and rarely encountered syntax checking for digraphs and trigraphs (this only improves compiler performance, not the speed of the compiled code).