2015-07-20 5 views
19

Недавно мы включили -Wall для проекта. Он включен, когда GCC находится на уровне 4.7 или выше (или Clang), потому что мы можем использовать GCC diagnostic для управления выходом с повышенными предупреждениями. Мы хотим управлять ими из исходного кода, а не через аргументы командной строки. (Мы не хотим загрязнять командную строку или попросить пользователей библиотеки заново открыть то, что необходимо).GCC не оценивает «pragma GCC diagnost» для предупреждения об отключении

Под GCC 4.8 и 5.1, мы догоняем предупреждения, которые были отключены в диагностическом блоке НКУ для -Wunused-variable, -Wunused-value, -Wunused-function и -Wunknown-pragmas. Оба ГЦСА принимает -fopenmp, и оба определяют _OPENMP в ответ на это, так что я довольно уверен, что мы никогда не должны видеть -Wunknown-pragmas в ответ на #prgam omp ... (это является отключена, но не неизвестна).

g++ -DNDEBUG -g2 -O3 -Wall -march=native -pipe -c nbtheory.cpp 
nbtheory.cpp:655:0: warning: ignoring #pragma omp parallel [-Wunknown-pragmas] 
    #pragma omp parallel 
^ 
nbtheory.cpp:656:0: warning: ignoring #pragma omp sections [-Wunknown-pragmas] 
    #pragma omp sections 
^ 
... 

В данном конкретном случае file nbtheroy.cpp имеет следующий охранник в месте, чтобы помочь управлять этим предупреждением (только соответствующие части показаны, но вы можете увидеть все от the GitHub link):

// Defines GCC_DIAGNOSTIC_AWARE if GCC 4.7 or above. 
#include <misc.h> 
... 

#if GCC_DIAGNOSTIC_AWARE 
# pragma GCC diagnostic ignored "-Wunknown-pragmas" 
#endif 

... 
Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, 
        const Integer &p, const Integer &q, const Integer &u) 
{ 
    Integer p2, q2; 
    #pragma omp parallel 
     #pragma omp sections 
     { 
      #pragma omp section 
       p2 = ModularExponentiation((a % p), dp, p); 
      #pragma omp section 
       q2 = ModularExponentiation((a % q), dq, q); 
     } 
    return CRT(p2, p, q2, q, u); 
} 
... 

Поскольку файл *.cpp (его эффективно блок перевода), мы не выполнить #pragma GCC diagnostic push в начале и #pragma GCC diagnostic pop в конце. (Мы делаем это для файлов заголовков, которые включены, однако). (Мы также пытались это сделать, но это не помогло).

А вот GCC_DIAGNOSTIC_AWARE (от misc.h):

// Used to suppress some warnings in some header and implementation files. 
// Some platforms, like CentOS and OpenBSD, use old compilers that don't understand -Wno-unknown-pragma. 
#define GCC_DIAGNOSTIC_AWARE ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__clang__)) 

Я знаю, что охранник работает, потому что добавление в блоке с #error вызывает ошибку. Кроме того, комментирование охранника и вызывание #pragma GCC diagnostic ignored "-Wunknown-pragmas" не помогает. Наконец, он отлично работает под Кланом.

Я также испытываю это для других предупреждений, таких как -Wunused-variable, -Wunused-value и -Wunused-function. I действительно не хотят загрязнять командную строку, как предполагалось, с помощью потенциального дубликата.

Как я могу получить механизм GCC pragma diagnostic для работы, как ожидается, для предупреждения об отключении под GCC при использовании -Wall?


Связанные, если вы хотите, чтобы воспроизвести его (ее GNUmakefile основе, и не требует конфигурации или Autotools):

git clone https://github.com/weidai11/cryptopp.git cryptopp-warn 
cd cryptopp-warn 
make 

EDIT: мы проверили в патч, который отключает -Wall кроме для Клана. Если вы хотите воспроизвести старое поведение, то:

git clone https://github.com/weidai11/cryptopp.git cryptopp-warn 
cd cryptopp-warn 
export CXXFLAGS="-g2 -O3 -DNDEBUG -Wall" 
make 
+1

Я бы предложил сначала удалить '# if/# endif' (оставив только' #pragma GCC ... '), чтобы увидеть, есть ли проблема с' GCC_DIAGNOSTIC_AWARE'. – paxdiablo

+0

Возможный дубликат [Suppress -Wunknown-pragmas warning in GCC] (http://stackoverflow.com/questions/12842306/suppress-wunknown-pragmas-warning-in-gcc) – nneonneo

+0

@paxdiablo - Нет радости. Я отключил охрану и выкрикнул «#pragma GCC diagnostic ignored» -Wunknown-pragmas »' непосредственно. – jww

ответ

9

Это, как представляется, ошибка в gcc по крайней мере.Следующий код:

#pragma GCC diagnostic ignored "-Wunknown-pragmas" 
#pragma GCC diagnostic ignored "-Wuninitialized" 

int fn(void) { 
    #pragma xyzzy 
    int x; 
    return x; 
} 

int main (void) { 
    return fn(); 
} 

не имеет никаких проблем, игнорируя неиницализированное x значения, но по-прежнему жалуется на прагма (без uninitialized прагмы, она генерирует предупреждение для x, как и следовало ожидать).

Если вы измените параметры командной строки на -Wall -Wno-unknown-pragmas, то она игнорирует ее просто отлично. Это нормально для вашего конкретного случая, так как вы хотите, чтобы он применялся по всей вашей единице перевода, но он не позволит мелкозернистый элемент управления, который вы получите от метода #pragma (если он сработает).


я пошел, чтобы поднять сообщение об ошибке в GCC, но обнаружил, что она уже существует (#53431).

Хотя эта конкретная ошибка связана с -Wundef, сниппет в одном из комментариев указывает на то, что он, вероятно, относится ко всем вариантам, влияющих на препроцессор (слегка измененный для выразительности):

C++ анализатор lexes (и preprocesses), прежде чем обращаться с прагмами, тогда как C-парсер обрабатывает прагмы, когда видит их.

Мы должны как-то разобрать эти прагмы также в cp/parser.c:631. Возможно, можно сделать что-то похожее на то, что мы делаем для cp_parser_initial_pragma, но в пределах цикла и только для обработки диагностики pragma. Разумеется, для правильной работы потребуется пробная версия и ошибка. Если кто-то из вас захочет попробовать и вам понадобится помощь, просто спросите здесь или в списке рассылки.

Это объясняет, почему мы не видим ту же проблему с -Wuninitialized, потому что он обнаружен на более поздних стадиях процесса компиляции, после того, как псевдокомментарии были активированы в конце предварительной обработки.

Итак, если вы хотите, чтобы это было исправлено более своевременно (оно было поднято более трех лет назад), я бы предложил (как я), чтобы скрыть сайт GCC bugzilla, чтобы попытаться получить некоторую экспозицию.

+0

Да, большая проблема - это код библиотеки. Поэтому нам нужно исправить это для работы с самой библиотекой. Это удобная вещь для нас. Но пользователи ожидают, что он «просто работает», когда они будут включать библиотеку. Если они включают библиотеку, а затем приходится перепрыгивать через обручи командной строки, потому что все не работает, тогда это проблема. – jww

+0

@jww, если вы выпускаете библиотеку ('.o/.a/.so/etc'), тогда предупреждение не произойдет. Или ваша библиотека на самом деле состоит из компилируемого источника? – paxdiablo

+0

Да, источники освобождены.Кроме того, некоторые заголовки выдают предупреждения, и мы пытаемся их отключить одним и тем же методом. – jww