GCC не соблюдает "Pragma GCC diagnostic", чтобы заставить замолчать предупреждения

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

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

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
 ^
...

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

// 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 (его эффективно the единица перевода), мы не выполнить #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. Я!--32-->действительно не хочу загрязнять командную строку, как это предлагается с потенциалом дубликат.

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


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

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

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

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

1 ответов


это похоже на ошибку в 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 pragma, он генерирует предупреждение для x как и следовало ожидать).

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


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

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

в C++ парсер половинки Лекса (и препроцессы) перед обработкой прагм, тогда как парсер C обрабатывает прагмы, как он их видит.

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

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

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