-Werror заставляет компилятор останавливаться при #warning. Что я могу сделать, чтобы предотвратить это?

Во-первых, я хочу, чтобы он останавливался на предупреждениях. Но я также хочу распечатать несколько информативных сообщений (например, «Вернись и реализуй это!»).

К сожалению, мой компилятор не поддерживает #info, #message, #pragma message() и т. д.

Я знаю, что есть -Wno-error=<something>, но у меня слабый google-foo, и я не могу найти <something> для #warning. Я пробовал -Wno-error=warning, и это просто говорит "нет -Wwarning". То же самое с "warn".

Какие-либо предложения?

Что бы это ни стоило, я использую компилятор Tensilica xtensa, xt-xcc, который, по-видимому, является производным от gnu или, по крайней мере, использует внешний интерфейс gnu. Это версия 8.0.0.


person Russ Schultz    schedule 06.12.2010    source источник
comment
Какой компилятор и версию используете?   -  person CharlesB    schedule 07.12.2010
comment
Поскольку вы говорите, что это производная GNU: опция -fdiagnostics-show-option для gcc сообщает вам, какая опция управляет каждым возникающим предупреждением. Может у xt-xcc есть такое?   -  person Cascabel    schedule 07.12.2010
comment
Другим вариантом было бы (очень некрасиво) индивидуально превращать все остальные предупреждения в ошибки.   -  person Cascabel    schedule 07.12.2010
comment
Я пробовал -fdiagnostics-show-option, и ничего лишнего не распечатывалось, так что это похоже на тупик. Я не уверен, из какой версии GCC он порождается (об этом не сообщается в его собственной информации о версии). И да, я не собираюсь превращать предупреждения в ошибки по одному.   -  person Russ Schultz    schedule 07.12.2010
comment
Метка изменена на встроенный, поскольку ниже вы указали, что это встроенный проект.   -  person JXG    schedule 05.05.2011
comment
@JXG: За исключением того, что вопрос не относится к «встроенным» и обычно применим к GCC. Не уверен, что это оправдывает встроенный тег.   -  person Clifford    schedule 07.05.2011
comment
-Wno-error=cpp работает с моей gcc версией 4.6.1 (см. мой ответ). Более новый gcc изящно называет название категории для предупреждения... :-)   -  person FooF    schedule 24.09.2012


Ответы (6)


Я не знаком с компилятором Tensilica xtensa (xt-xcc), но со стандартным gcc можно использовать

  #pragma GCC diagnostic warning "-Wcpp"

сделать #warning простым предупреждением (а не ошибкой из-за -Werror). Чтобы сделать эффект временным, вы можете использовать #pragma и #warning между #pragma GCC diagnostic push и #pragma GCC diagnostic pop.

Когда я компилирую файл, содержащий следующее

    #pragma GCC diagnostic push
    #pragma GCC diagnostic warning "-Wcpp"
    #warning one
    #pragma GCC diagnostic pop

    #warning two

с -Werror с помощью gcc 4.6.1 (команда gcc -c -Werror warning-test.c) я получаю следующий вывод:

    warning-test.c:3:2: warning: #warning one [-Wcpp]
    warning-test.c:6:2: error: #warning two [-Werror=cpp]
    cc1: all warnings being treated as errors

Когда я удаляю второй #warning, компиляция не прерывается по ошибке.

Вы также можете заменить параметры компилятора -Werror на -Werror -Wno-error=cpp. Я не знаю, какие другие эффекты включает в себя категория предупреждений cpp (и у вас может быть законное #warning в каком-то другом месте, которое вы хотите отловить как ошибку), поэтому временно отключите ошибку для определенного #warning и восстановите настройки сразу после того, как кажется более точный метод удовлетворения ваших требований.

Edit (2016): использование gcc версий 4.8.4 и 4.9.2 дает почти такое же поведение (только дополнительно распечатывается исходная строка). Но использование gcc версии 5.0.1 (предварительная версия, включенная в Ubuntu 15.04) выдаст два предупреждения, если также не включена опция -Werror=cpp. Таким образом, кажется, что -Werror с более новым gcc больше не подразумевает -Werror=cpp, как раньше, и при желании его необходимо указать отдельно.

person FooF    schedule 24.09.2012
comment
Проголосовал, но приведенный выше фрагмент по-прежнему не работает для меня (используя gcc 4.8.4) - person Maghoumi; 10.08.2016
comment
@ M2X - как не получается? Вам нужно включить опцию -c (только для компиляции); в противном случае gcc попытается связать, и это не удастся из-за отсутствия функции main(), я думаю. Я тестировал с gcc 4.8.4 и 4.9.2, и ничего существенно не изменилось с тех пор, как я изначально написал этот ответ. Однако использование gcc 5.0 -Werror больше не подразумевает -Werror=cpp. - person FooF; 10.08.2016
comment
@FooF Я должен был быть более ясным. Я не говорил о вашем фрагменте кода (с main) выше. Я работаю над большим проектом, в котором включен -Werror. Я пытаюсь заставить gcc игнорировать некоторые #warning в некоторых заголовках Qt. Когда я добавил #pragma GCC diagnostic warning "-Wcpp" перед включением этих заголовков, я все еще получаю сообщение об ошибке (вместо предупреждения), когда компилятор достигает этой строки #warning... Есть мысли? - person Maghoumi; 10.08.2016
comment
@ M2X - Ваш gcc работает так, как описано выше для этого фрагмента? У меня нет времени исследовать вашу проблему, но вы пробовали, может быть (нажали или все) #pragma GCC diagnostic вещи сбрасываются во время #include как-то? В противном случае, возможно, вы могли бы просто рассмотреть возможность добавления -Eno-error=cpp к флагам вашего компилятора, если вы не хотите останавливаться при встрече с другими #warning, которых там быть не должно. Конечно, вы также можете проверить документацию GCC для получения дополнительной информации об этих #pragma штуковинах. - person FooF; 11.08.2016

К сожалению, для моей конкретной цепочки инструментов нет ответа, по крайней мере, так говорят инженеры Tensilica. Они не поддерживают #message или #pramga message() и не знают, как подавить #warning как ошибку при наличии -Werror.

Инструментальная цепочка GCC позволяет использовать -Wno-error=[код], чтобы сказать, что «это предупреждение НЕ является ошибкой», но я не нашел списка, соответствующего #warning какому-либо коду, который потребуется (или даже списка коды это может быть)

Я могу попытаться найти время, чтобы углубиться в стандартные командные строки GCC и исходный код препроцессора, чтобы попытаться найти список того, чему может быть равен -Wno-error=, или есть ли код -Werror=, который соответствует #предупреждение. Если я это сделаю, я вернусь и обновлю ответ.

person Russ Schultz    schedule 07.12.2010

Что случилось с:

#warning "Come back and implement this"
#warning "Do not do that!"
#warning "Must fix this before release"

Обычно компилятор включает аргумент(ы) до - или материал после - #warning в сообщении об ошибке или предупреждении.

И, как правило, если компилятор обнаруживает что-то, требующее предупреждения, он довольно четко сообщает об этом.


Учитывая требования, я думаю, что единственный способ справиться с этим - защитить директивы #warning...

#ifdef DO_WARNINGS
#warning "Some warning"
#endif /* DO_WARNINGS */

В большинстве случаев вы компилируете без -DDO_WARNINGS; когда вам нужно проверить предупреждения #warning-Werror), вы в конце концов включаете -DDO_WARNINGS, соглашаясь с тем, что компиляция завершится ошибкой. Помните, что make -k сделает все возможное даже при наличии отдельных ошибок компиляции.


В разделе 5.52.9 руководства GCC 4.4.1 говорится (частично):

5.52.9 Диагностические прагмы

GCC позволяет пользователю выборочно включать или отключать определенные типы диагностики и изменять тип диагностики. Например, политика проекта может требовать, чтобы все исходные коды компилировались с параметром «-Werror», но некоторые файлы могут иметь исключения, допускающие определенные типы предупреждений. Или проект может выборочно включать диагностику и рассматривать их как ошибки в зависимости от того, какие макросы препроцессора определены.

#pragma GCC diagnostic kind option

Изменяет расположение диагностики. Обратите внимание, что не все диагностические данные можно изменить; на данный момент можно управлять только предупреждениями (обычно управляемыми ‘-W...’), а не всеми. Используйте «-fdiagnostics-show-option», чтобы определить, какие диагностики являются управляемыми и какой параметр ими управляет. типом является «ошибка», чтобы рассматривать эту диагностику как ошибку, «предупреждение», чтобы рассматривать ее как предупреждение (даже если действует «-Werror»), или «игнорировать», если диагностику следует игнорировать. option — это строка в двойных кавычках, которая соответствует параметру командной строки.

#pragma GCC diagnostic warning "-Wformat"
#pragma GCC diagnostic error "-Wformat"
#pragma GCC diagnostic ignored "-Wformat"

Обратите внимание, что эти прагмы переопределяют любые параметры командной строки. Кроме того, хотя синтаксически допустимо размещать эти прагмы в любом месте ваших источников, единственное поддерживаемое место для них — до того, как будут определены какие-либо данные или функции. В противном случае это может привести к непредсказуемым результатам в зависимости от того, как оптимизатор управляет вашими источниками. Если одна и та же опция указана несколько раз, действует последняя указанная опция. Эта прагма предназначена не для замены параметров командной строки общего назначения, а для реализации строгого контроля над политиками проекта.

GCC также предлагает простой механизм для вывода сообщений во время компиляции.

#pragma message string

Выводит строку как сообщение компилятора при компиляции. Сообщение носит только информационный характер и не является ни предупреждением компиляции, ни ошибкой.

#pragma message "Compiling " __FILE__ "..."

строка может быть заключена в круглые скобки и печатается с информацией о местоположении.

Я не уверен, хотите ли вы преобразовать свои #warning строк в #pragma message строк. Это избавит вас от проблемы - и это только хуже, чем добавление условной компиляции вокруг #warning, поскольку #pragma message может поддерживаться меньшим количеством компиляторов. Это зависит от ваших требований к переносимости.

person Jonathan Leffler    schedule 07.12.2010
comment
Суть проблемы в том, что #warning приводит к остановке компиляции, когда -Werror находится в командной строке, и я не знаю, как переопределить это, кроме удаления -Werror, что невозможно. - person Russ Schultz; 07.12.2010
comment
Вы хотите, чтобы предупреждения были ошибками, за исключением тех случаев, когда они должны быть предупреждениями? Сложно... если не сказать противоречиво. - person Jonathan Leffler; 07.12.2010
comment
Ну, я хочу, чтобы предупреждения были ошибками, кроме этого (или этого класса). Я просто не знаю, что передать -Wno-error=???? чтобы не рассматривать #warning как ошибку. Это или я хотел бы, чтобы инструменты предлагали #message или #pragma message() или что-то подобное. - person Russ Schultz; 07.12.2010
comment
Я не думаю, что это возможно с текущей кодовой базой GCC. -Werror превращает любое предупреждение из любого источника в ошибку (как вы прекрасно знаете), и, насколько вам известно, избежать этого невозможно. Вам придется обойтись без предупреждений или защитить их с помощью #ifdef DO_WARNINGS / #warning "Some warning" / #endif. - person Jonathan Leffler; 08.12.2010
comment
-Wno-error=implicit, например, делает так, что предупреждения о неявных вызовах функций не рассматриваются как ошибки даже при наличии -Werror. Я надеялся, что коллективное знание Интернета будет знать волшебное заклинание, описывающее класс предупреждений, которые являются #warning, чтобы я мог отключить это подобно тому, как могли бы быть другие классы предупреждений. - person Russ Schultz; 08.12.2010

Учитывая, что #warning предположительно обрабатывается препроцессором, вы можете запустить препроцессор отдельно без -Werror, а затем запустить компилятор с запрещенной предварительной обработкой на выходе пропроцессора.

Для этого пропустите файл .c через препроцессор со всеми обычными параметрами, кроме -Werror, и сгенерируйте выходные данные в виде файла .i (.ii для C++). Компилятор распознает эти файлы как не подлежащие предварительной обработке, поэтому вы можете скомпилировать их с параметром -Werror и предположить, что препроцессор сбрасывает #warning и не обрабатывается самим компилятором, это может решить вашу проблему.

Я не проверял это; когда я столкнулся с той же проблемой, я просто решил жить с ней и не использовать -Werror. Решение казалось более сложным, чем проблема!

person Clifford    schedule 05.05.2011
comment
Я выбрал тот же маршрут. Цель для меня не в том, чтобы иметь ноль предупреждений. Цель состоит в том, чтобы иметь только предупреждения, генерируемые директивой #warning, и достаточно мало, чтобы вам не приходилось прокручивать их, чтобы прочитать их все. Это работает в коммерческом проекте размером +100KLOC с участием четырех-пяти человек. Встроенный код реального времени, написанный на C. - person Morten Jensen; 10.08.2016

Десять лет спустя правильный способ выдавать предупреждения и избегать этих дополнительных сообщений/ошибок от -Wpedantic — использовать #pragma message. GCC поддерживает этот синтаксис, начиная с GCC 4.5 и clang, по крайней мере, с Клэнг 6.

Современные версии этих компиляторов даже поддерживают #pragma GCC error "message" и #pragma GCC warning "message" (GCC9, уже поддерживается в Clang 6)

person akim    schedule 31.01.2021
comment
Я обнаружил, что #pragma GCC warning "message" все еще вызывает ошибку. - person parsley72; 01.04.2021
comment
Возможно, вы проходите -Werror. И поскольку вы не указываете версию GCC, трудно понять, какая у вас проблема. - person akim; 01.04.2021
comment
Я передаю -Werror, вот о чем был первоначальный вопрос. - person parsley72; 04.04.2021

Если ваш компилятор поддерживает это, вы можете попробовать использовать constructor атрибут функции для определения функции, которая запускается при запуске программы (до main) и выводит сообщение на стандартный вывод:

#define TOKENPASTE(x, y) TOKENPASTE2(x, y)
#define TOKENPASTE2(x, y) x ## y
#define WARNING(message) \
  static void TOKENPASTE(_print_warning, __LINE__)() __attribute__((constructor)); \
  static void TOKENPASTE(_print_warning, __LINE__)() \
  { \
    puts(message); \
  }

WARNING("fix this before ship")  // prints out a message at runtime before main

Это заставляет сообщение распечатываться во время выполнения, а не во время компиляции, что почти так же хорошо, особенно если у вас нет других вариантов. Единственное ограничение состоит в том, что вы должны использовать это в глобальном масштабе вне определения функции.

person Adam Rosenfield    schedule 07.12.2010
comment
Это встроенный проект, в котором нет ни консоли, ни экрана. - person Russ Schultz; 07.12.2010