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

7 ответов

Я не знаком с компилятором 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 и восстановление настроек сразу после этого кажется более точным способом удовлетворения ваших требований.

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

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

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

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

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

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

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

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

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

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

#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', чтобы определить, какие диагностики являются управляемыми, а какая опция управляет ими. kind - это "error", чтобы рассматривать эту диагностику как ошибку, "warning", чтобы рассматривать ее как предупреждение (даже если действует "-Werror"), или "ignored", если диагностика должна игнорироваться. 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 может поддерживаться меньшим количеством компиляторов. Это зависит от ваших требований к мобильности.

Если ваш компилятор поддерживает это, вы можете попробовать использовать constructor Атрибут function для определения функции, которая запускается при запуске программы (до 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

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

кажется, работает с недавними звуками (проверено 14..17)

G++ (11 и 12) не поддерживает эквивалент и предлагает использовать- это не то, чего ты хочешь.

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

Другие вопросы по тегам