Включение ‹atomic› нарушает диагностику преобразования GCC-null, а distcc исправляет это. (Включено минимальное количество примеров)

Этот вопрос на самом деле состоит из двух наблюдений.

Во-первых: включение <atomic> приводит к тому, что GCC не выдает диагностику conversion-null, по крайней мере, в некоторых случаях, когда в противном случае это происходит.
Например, рассмотрим файл noerror.cpp:

#include <atomic>
#pragma GCC diagnostic error "-Wconversion-null"
int * foo() {return false;}

Этот файл (error.cpp) идентичен, за исключением закомментированного включения:

//#include <atomic>
#pragma GCC diagnostic error "-Wconversion-null"
int * foo() {return false;}

Если я попытаюсь скомпилировать error.cpp, я получу ошибку, как и ожидалось:

$ g++-4.8 -c -std=c++11 error.cpp
error.cpp: In function ‘int* foo()’:
error.cpp:3:21: error: converting ‘false’ to pointer type ‘int*’ [-Werror=conversion-null]
 int * foo() {return false;}
                     ^
cc1plus: some warnings being treated as errors

Я получаю те же результаты, если я опускаю #pragma и вместо этого компилирую с -Werror. Это также ожидается: согласно документам GCC, предупреждение включено по умолчанию.

К моему удивлению, я могу скомпилировать noerror.cpp без ошибок. Даже если заголовок <atomic> подавлял предупреждения и ошибки через #pragma GCC diagnostic ignore, прагма в моем коде должна снова включить их, но это не так.

Между прочим, clang++ ошибок, как и ожидалось, независимо от того, включен ли заголовок:

error: cannot initialize return object of type 'int *' with an rvalue of type 'bool'

Во-вторых: работа с distcc восстанавливает правильное поведение
У меня несколько рабочих станций. Если я попытаюсь построить локально на любом из них, я столкнусь с описанным выше поведением. Однако, если distcc попытается построить его на любой удаленной машине, ошибка будет выдана корректно. (Именно так я обнаружил эту проблему в первую очередь; наша сборка с высокой вероятностью заставит distcc откатиться к локальной компиляции). На самом деле, даже если у меня есть distcc SSH к моей собственной машине, правильное поведение (то есть ошибка) восстанавливается:

$ DISTCC_HOSTS='localhost' distcc g++-4.8 -c -std=c++11 noerror.cpp # no error
$ DISTCC_HOSTS='@[my_ip_address]' distcc g++-4.8 -c -std=c++11 noerror.cpp
noerror.cpp: In function ‘int* foo()’:
noerror.cpp:3:21: error: converting ‘false’ to pointer type ‘int*’ [-Werror=conversion-null]
cc1plus: some warnings being treated as errors

Мне непонятно, как distcc удается восстановить правильное поведение.

Информация о версии: я использую Ubuntu 3.5.0-46-generic, GCC 4.8.1 и distcc 3.1.

Резюме

Включение <atomic>, похоже, нарушает диагностику GCC conversion-null. И каким-то образом использование distcc исправляет это. Я искал, но не смог найти никаких ссылок на подобную ошибку. Является ли эта экспериментальная ошибка известной проблемой или мне следует отправить отчет об ошибке GCC?

[Редактировать: фрагменты кода были взяты с того момента, когда я сделал это предупреждением, а не ошибкой. Вставил исправленную версию]


person Tom    schedule 20.02.2014    source источник
comment
gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html что #pragma GCC diagnostic error действительно не выглядит хорошей идеей   -  person user2485710    schedule 21.02.2014
comment
@ user2485710 Обычно я использую флаги командной строки. Тем не менее, я хотел рассмотреть возможность того, что заголовок <atomic> отключил эту диагностику внутри с помощью прагм и забыл сбросить ее (например, push, но не pop). Можешь уточнить, почему ты считаешь это плохой идеей?   -  person Tom    schedule 21.02.2014
comment
не имеет значения, в документации gcc ясно сказано, что этот #pragma ведет себя непоследовательно. Вы не можете сказать, что это не работает, если такой подход даже не должен работать с самого начала. Просто всегда используйте параметры командной строки, это не то, что вам нужно.   -  person user2485710    schedule 21.02.2014
comment
@user2485710 user2485710 В документации указано, что некоторые предупреждения можно контролировать, и я убедился, что прагма работает для этого конкретного предупреждения. Несмотря на это, вы неконструктивны: У меня такое же поведение, если я укажу его в командной строке, как я указал в вопросе   -  person Tom    schedule 21.02.2014


Ответы (1)


Кроме того, я обнаружил, что это происходит только при объединении компиляции и предварительной обработки в один шаг. Это объясняет разницу в поведении при использовании distcc: он предварительно обрабатывает весь код на локальном компьютере и компилирует его удаленно.

Несмотря на комментарии @user2485710 об обратном, это не случай ошибки пилота или использования плохо документированной функции. Это добросовестная ошибка, и я сообщил о ней следующим образом:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60304

[На данный момент проблема не решена, но Харальд ван Дейк отметил, что GCC подавляет предупреждение, потому что (ошибочно) считает, что оно находится в системном заголовке. Ошибка/предупреждение могут быть повторно выставлены с помощью -Wsystem-headers.]

person Tom    schedule 25.02.2014