- Ошибка приводит к остановке компилятора на #warning. Что я могу сделать, чтобы предотвратить это? - PullRequest
7 голосов
/ 07 декабря 2010

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

К сожалению, мой компилятор не поддерживает #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.

Ответы [ 5 ]

3 голосов
/ 24 сентября 2012

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

1 голос
/ 05 мая 2011

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

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

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

1 голос
/ 07 декабря 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', чтобы определить, какие диагностики являются управляемыми, а какая опция управляет ими.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 может поддерживаться меньшим количеством компиляторов.Это зависит от ваших требований к мобильности.

0 голосов
/ 08 декабря 2010

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

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

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

0 голосов
/ 07 декабря 2010

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

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

...