Background
In the last year I was using the nlohmann json library[1] and was cross-compiling on x86_64 using GCC 5.x arm-linux-gnueabi-*
with no warnings. When I updated GCC to a newer version, GCC would generate pages of cryptic diagnostic notes. For example, here is one of the notes
In file included from /usr/arm-linux-gnueabi/include/c++/7/vector:69:0,
from include/json.hpp:58,
from src/write_hsi.cpp:23:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc: In member function ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long long int, long long unsigned int, double, std::allocator, nlohmann::adl_serializer>}; _Tp = nlohmann::basic_json<>; _Alloc = std::allocator<nlohmann::basic_json<> >]’:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc:394:7: note: parameter passing for argument of type ‘std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > >::iterator {aka __gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > > >}’ changed in GCC 7.1
vector<_Tp, _Alloc>::
^~~~~~~~~~~~~~~~~~~
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc: In member function ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer> nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer>::parser::parse_internal(bool) [with ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer]’:
/usr/arm-linux-gnueabi/include/c++/7/bits/vector.tcc:105:21: note: parameter passing for argument of type ‘__gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<>, std::allocator<nlohmann::basic_json<> > > >’ changed in GCC 7.1
_M_realloc_insert(end(), std::forward<_Args>(__args)...);
~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It was easy to find a solution, namely by adding -Wno-psabi
to the compiler options. In fact, that was the fix implemented in the library.[2]
I understand the basics of Application Binary Interfaces (ABIs) and processor-specific ABIs (psABIs). For reference, this answer[11] gives a quick overview of ABIs:
An ABI (Application Binary Interface) is a standard that defines a mapping between low-level concepts in high-level languages and the abilities of a specific hardware/OS platform's machine code. That includes things like:
- how C/C++/Fortran/... data types are laid out in memory (data sizes / alignments)
- how nested function calls work (where and how the information on how to return to a function's caller is stored, where in the CPU registers and/or in memory function arguments are passed)
- how program startup / initialization works (what data format an "executable" has, how the code / data is loaded from there, how DLLs work ...)
The answers to these are:
- language-specific (hence you've got a C ABI, C++ ABI, Fortran ABI, Pascal ABI, ... even the Java bytecode spec, although targeting a "virtual" processor instead of real hardware, is an ABI),
- operating-system specific (MS Windows and Linux on the same hardware use a different ABI),
- hardware/CPU-specific (the ARM and x86 ABIs are different).
- evolving over (long) time (existing ABIs have often been updated / rev'ed so that new CPU features could be made use of, like, say, specifying how the x86 SSE registers are to be used by apps was of course only possible once CPUs had these regs, therefore existing ABIs needed to be clarified).
So the ABI is the overarching component, and one of its components (the "hardware/CPU-specific" details) is the psABI.
My Issue
The problem I am having is
- I don't like universally disabling warnings without understanding the implications.
- The advice "use
-Wno-psabi
to make the notes go away" seems to be pretty common advice for these types of diagnostic notes that "suddenly appear" after a compiler upgrade.[2][3][4] Even the one of the GCC developers suggest doing this.[5] - Neither
-Wpsabi
nor-Wno-psabi
are documented[6] in the GCC manual.[7]
As a result I am not really sure what exactly -Wno-psabi
will and will not affect. A related option -Wabi
is documented:[8]
-Wabi (C, Objective-C, C++ and Objective-C++ only)
Warn when G++ it generates code that is probably not compatible with the vendor-neutral C++ ABI...
It also warns about psABI-related changes. The known psABI changes at this point include:
- For SysV/x86-64, unions with long double members are passed in memory as specified in psABI. For example:
union U {
long double ld;
int i;
};
union U
is always passed in memory.
My understanding of this all is
-Wabi
will generate warnings when there is a psABI change.- GCC 7 fixed an ABI bug[9] introduced in GCC 5 that affects ARM targets.
- In the release notes it is stated "this is an ABI change."[10]
- For some reason the release notes state that the related diagnostic notes are generated when using the undocumented
-Wpsabi
, not the documented-Wabi
. - This ABI change is not mentioned in the manual.
- Putting together "this is an ABI change" and "use
-Wpsabi
", it appears to me this is specifically a psABI change, not a different kind of ABI change. (In reality it is a change in GCC's implementation of the psABI, not the psABI itself)
I know that documentation isn't always up to date, especially for something that is a known undocumented option. But my concern is that "use -Wno-psabi
" seems to be the standard response for several different kinds of these cryptic diagnostic notes. But, in my basic understanding of ABIs, isn't an ABI change a big deal? Shouldn't I be concerned about an ABI change, rather than just making the message go away? Between the undocumented stuff and some of the finer details of ABI vs psABI, I'm not really sure...
For example, if I add -Wno-psabi
to my makefile to make those notes go away, what if there is another ABI change in the future that does affect my project? Have I effectively silenced future warnings or notes that may be important?
Also, even though we are told "if you recompile all the code, there is nothing to worry about,"[5] what exactly is "all the code"? Is that my source code? glibc? Any other system-wide shared library I might be using?
References
- https://github.com/nlohmann/json
- https://github.com/nlohmann/json/issues/658
- https://stackoverflow.com/a/48149400
- https://mcmap.net/q/218299/-remove-note-of-gcc-abi-change
- https://gcc.gnu.org/ml/gcc/2017-05/msg00073.html
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81831
- https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc
- https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/C_002b_002b-Dialect-Options.html
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728
- https://gcc.gnu.org/gcc-7/changes.html
- https://stackoverflow.com/a/8063350
-Wpsabi
affects (the first part of the question). – Ironware-Wabi
should apply also for-Wpsabi
/-Wno-psabi
, where the latter refers to the changes due to conformance to the PS ABI rather than the ABI. – Novotny-Wpsabi
. The ABI change warning I experienced occurred after updating from GCC 5.x to a newer version (I can't remember if it was a newer 5.x or 6.x). The GCC 9 changes you linked are for a bug "On Arm targets... in the GCC 6, 7 and 8 releases... This is an ABI change. If the option -Wpsabi is enabled... the compiler will emit a diagnostic note..." If I had put -Wno-psabi in my makefile 2 years ago while using GCC 5.x, it would have suppressed warnings on this later ABI change. – Ironware