Что именно делает опция GCC -Wpsabi?Каковы последствия подавления этого? - PullRequest
0 голосов
/ 25 августа 2018

Фон

В прошлом году я использовал библиотеку nlohmann json [1] и выполнял кросс-компиляцию на x86_64 с использованием GCC 5.x arm-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).Для справки, этот ответ [11] дает краткий обзор ABI:

ABI ( двоичный интерфейс приложения )стандарт, который определяет соответствие между понятиями низкого уровня в языках высокого уровня и возможностями машинного кода конкретной аппаратной / операционной системы.Это включает в себя такие вещи, как:

  • как C / C ++ / Fortran / ... типы данных расположены в памяти (размеры данных / выравнивания)
  • howработают вложенные вызовы функций (где и как хранится информация о том, как вернуться к вызывающей функции, где в регистры ЦП и / или в память передаются аргументы функций)
  • как запуск / инициализация программы работает (какой формат данных имеет "исполняемый файл", как оттуда загружается код / ​​данные, как работают библиотеки DLL ...)

Ответы на эти вопросыявляются:

  • для конкретного языка (следовательно, у вас есть C ABI, C ++ ABI, Fortran ABI, Pascal ABI, ... даже спецификация Java-байт-кода, хотя и нацеленная«виртуальный» процессор вместо реального оборудования (ABI),
  • для конкретной операционной системы (MS Windows и Linux на одном оборудовании используют другой ABI),
  • для оборудования / процессора (ABI ARM и x86 отличаются).
  • эволюционирование в течение (длительного) времени (существующие ABI часто обновлялись / обновлялись, чтобы можно было использовать новые функции ЦП, как, например, указание того, как регистры SSE x86 должны использоваться приложениями, былоконечно, это возможно только тогда, когда процессоры имеют этих регистров, поэтому необходимо прояснить существующие ABI).

Таким образом, ABI является всеобъемлющим компонентом и одним из его компонентов(«специфичные для оборудования / процессора») - это psABI.

My Issue

Проблема, с которой я сталкиваюсь,

  1. Мне не нравится универсальноотключение предупреждений без понимания последствий.
  2. Рекомендация «используйте -Wno-psabi, чтобы убрать заметки», кажется довольно распространенным советом для этих типов диагностических заметок, которые «внезапно появляются» после обновления компилятора. [2] [3] [4] Даже один из разработчиков GCC предлагает сделать это. [5]
  3. Ни -Wpsabi, ни -Wno-psabi не задокументированы [6] в GCC маnual. [7]

В результате я не совсем уверен, что именно -Wno-psabi повлияет и не повлияет.Связанная опция -Wabi задокументирована : [8]

-Wabi (C, Objective-C, C++ and Objective-C++ only)

Предупредить, когда G ++ генерирует код, которыйвероятно, не совместим с независимым от производителя C ++ ABI ...

Он также предупреждает об изменениях, связанных с psABI.Известные изменения psABI на этом этапе включают:

  • Для SysV / x86-64 объединения с длинными двойными членами передаются в память, как указано в psABI.Например:

union U { long double ld; int i; };

union U всегда передается в память.

Мое пониманиевсе это

  1. -Wabi будет генерировать предупреждения при изменении psABI.
  2. GCC 7 исправил ошибку ABI [9] , введенную в GCC5, которая влияет на цели ARM.
    • В примечаниях к выпуску указано "это изменение ABI". [10]
    • По некоторым причинам в примечаниях к выпуску говорится, что соответствующие диагностические примечания генерируются при использовании недокументированного -Wpsabi, а не документированного -Wabi.
    • Это изменение ABI не упоминается в руководстве.
  3. Соединяя «это изменение ABI» и «используйте -Wpsabi», мне кажется, это конкретно изменение psABI, а не другой вид изменения ABI. (На самом деле это изменение реализации psABI в GCC, а не в самой psABI)

Я знаю, что документация не всегда актуальна, особенно для чего-то, что является известным недокументированным вариантом. Но меня беспокоит то, что «use -Wno-psabi», по-видимому, является стандартным ответом на несколько разных видов этих загадочных диагностических заметок. Но, в моем базовом понимании ABI, разве ABI не меняет дело? Разве я не должен беспокоиться об изменении ABI, вместо того, чтобы просто пропустить сообщение? Между недокументированным материалом и некоторыми мелочами ABI против psABI я не совсем уверен ...

Например, если я добавлю -Wno-psabi в свой make-файл, чтобы эти заметки исчезли, что если в будущем произойдет еще одно изменение ABI, которое повлияет на мой проект ? Эффективно ли я заставил замолчать будущие предупреждения или заметки, которые могут быть важны?

Кроме того, даже несмотря на то, что нам говорят: «если вы перекомпилируете весь код, вам не о чем беспокоиться» [5] что такое «весь код»? Это мой исходный код? GLibC? Любая другая общесистемная общая библиотека, которую я мог бы использовать?

Ссылки

  1. https://github.com/nlohmann/json
  2. https://github.com/nlohmann/json/issues/658
  3. https://stackoverflow.com/a/48149400
  4. https://stackoverflow.com/a/13915796/10270632
  5. https://gcc.gnu.org/ml/gcc/2017-05/msg00073.html
  6. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81831
  7. https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc
  8. https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/C_002b_002b-Dialect-Options.html
  9. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77728
  10. https://gcc.gnu.org/gcc-7/changes.html
  11. https://stackoverflow.com/a/8063350

1 Ответ

0 голосов
/ 18 сентября 2018

Вам нужно беспокоиться только о ABI, когда вы пересекаете границы библиотеки. В ваших собственных приложениях / библиотеках ABI на самом деле не имеет значения, так как предположительно все ваши объектные файлы скомпилированы с одинаковой версией компилятора и переключателями.

Если у вас есть библиотека, скомпилированная с ABI1, и приложение, скомпилированное с ABI2, то приложение будет аварийно завершать работу при попытке вызвать функции из библиотеки, поскольку оно не будет правильно передавать аргументы. Чтобы исправить ошибку, вам нужно перекомпилировать библиотеку (и любые другие библиотеки, от которых она зависит) с ABI2.

В вашем конкретном случае, если вы компилируете nlohmann с той же версией компилятора, что и ваше приложение (или просто используете nlohmann в качестве заголовка), вам не нужно беспокоиться об изменении ABI.

Глобальное подавление предупреждения представляется опасным вариантом, поскольку оно не позволит вам увидеть какие-либо будущие проблемы с ABI. Лучшим вариантом было бы использовать #pragma для отключения предупреждения только для рассматриваемых функций, например ::

.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wno-psabi"
void foo()
{
}
#pragma GCC diagnostic pop
...