背景
去年我使用了nlohmann json库[1],并且在x86_64上使用GCC 5.xarm-linux-gnueabi-*
进行交叉编译时没有收到任何警告。当我将GCC更新到新版本时,GCC会生成大量晦涩难懂的诊断信息。例如,下面是其中一个诊断信息的示例:
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)...);
~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
解决方案很简单,只需将-Wno-psabi
添加到编译器选项中即可。实际上,这也是库中实现的修复措施。[2]
我了解应用程序二进制接口(ABI)和处理器特定ABI(psABI)的基本知识。有关ABI的快速概述,请参见此答案[11]:
ABI(应用程序二进制接口)是一种标准,它定义了高级语言中的低级概念与特定硬件/操作系统平台机器代码的功能之间的映射。这包括诸如:
- C/C++/Fortran/ ...数据类型在内存中的布局方式(数据大小/对齐方式)
- 嵌套的函数调用如何工作(返回到函数调用者的信息存储在哪里以及如何存储在CPU寄存器和/或内存中的函数参数传递方式)
- 程序启动/初始化如何工作(“可执行文件”具有什么数据格式,代码/数据如何从中加载,DLL如何工作...)
这些问题的答案是:
- 特定于语言(因此您有C ABI、C++ ABI、Fortran ABI、Pascal ABI等,即使是针对虚拟处理器而不是实际硬件的Java字节码规范也是ABI)
- 特定于操作系统(MS Windows和Linux在同一硬件上使用不同的ABI)
- 特定于硬件/CPU(ARM和x86 ABIs不同)。
- 随着时间的推移而不断发展(现有ABI经常被更新/修订,以便可以利用新的CPU功能,例如指定应用程序如何使用x86 SSE寄存器当然只有在CPU拥有这些寄存器后才有可能,因此需要澄清现有ABI)。
因此,ABI是一个总体组件,其中之一组成部分(“硬件/CPU特定”细节)是psABI。
我的问题
我遇到的问题是
- 我不喜欢在不了解影响的情况下普遍禁用警告。
- 建议“使用
-Wno-psabi
使笔记消失”似乎是这些编译器升级后“突然出现”的此类诊断笔记的常见建议。[2][3][4]甚至GCC开发人员中的一个也建议这样做。[5] - 无论是
-Wpsabi
还是-Wno-psabi
都没有在GCC手册[7]中记录[6]。
因此,我不太确定-Wno-psabi
会影响什么以及不会影响什么。相关选项-Wabi
已记录:[8]
-Wabi(仅限C、Objective-C、C++和Objective-C ++)
当 G++ 生成与厂商中性 C++ ABI 不兼容的代码时,它会发出警告...
它还警告有关 psABI 相关更改的情况。此时已知的 psABI 更改包括:
- 对于 SysV/x86-64,具有 long double 成员的 union 按照 psABI 规定在内存中传递。例如:
union U {
long double ld;
int i;
};
union U
总是在内存中传递。参考文献
- https://github.com/nlohmann/json
- https://github.com/nlohmann/json/issues/658
- https://dev59.com/v1YM5IYBdhLWcg3w-Dtf#48149400
- https://dev59.com/u2Yr5IYBdhLWcg3wJ3CU#13915796
- 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://dev59.com/gGsz5IYBdhLWcg3wNE5q#8063350