предупреждения пользователя на msvc и gcc? - PullRequest
15 голосов
/ 23 января 2009

В MSVC у меня это в шапке:

#define STR(x)          #x
#define STR2(x)         STR(x)
#define NOTE(text)      message (__FILE__ "(" STR2(__LINE__) ") : -NOTE- " #text)
#define noteMacro(text) message (__FILE__ "(" STR2(__LINE__) ") : " STR2(text))

и я

#pragma NOTE(my warning here)

GCC имеет:

#warning(my warning here)

Тем не менее, MSVC (2003) выбрасывает фитинг, когда видит #warning и выдает «фатальную ошибку C1021: недопустимая команда препроцессора« предупреждение »»

Что я могу с этим сделать? Есть ли способ заставить GCC распознавать предупреждения MSVC или MSVC не выдавать ошибку в предупреждениях GCC? Есть ли что-то, что я могу сделать, что работает на обоих? Я могу попросить GCC предупредить меня о неизвестных прагмах, но это не самое идеальное решение.

Ответы [ 5 ]

15 голосов
/ 16 декабря 2009

Лучшее решение, которое я нашел для этой проблемы, это иметь следующее в общем заголовке:

// compiler_warning.h
#define STRINGISE_IMPL(x) #x
#define STRINGISE(x) STRINGISE_IMPL(x)

// Use: #pragma message WARN("My message")
#if _MSC_VER
#   define FILE_LINE_LINK __FILE__ "(" STRINGISE(__LINE__) ") : "
#   define WARN(exp) (FILE_LINE_LINK "WARNING: " exp)
#else//__GNUC__ - may need other defines for different compilers
#   define WARN(exp) ("WARNING: " exp)
#endif

Тогда используйте

#pragma message WARN("your warning message here")

по всему коду вместо # предупреждение

В MSVC вы получите следующее сообщение:

c:\programming\some_file.cpp(3) : WARNING: your warning message here

Под gcc вы получите:

c:\programming\some_file.cpp:25: note: #pragma message: WARNING: your warning message here

Не идеально, но разумный компромисс.

6 голосов
/ 23 января 2009

Как вы теперь обнаружили, #warning не является стандартной функцией, поэтому вы не можете использовать ее с компиляторами, которые ее не поддерживают. Если вы хотите, чтобы ваш код работал на разных платформах, вы вообще не будете использовать #warning - или, по крайней мере, не в коде, который MSVC предназначен для обработки (он может быть предварительно обработан #ifdef или эквивалентным). Следовательно:

#ifdef __GNUC__
#warning(warning message)
#else
#pragma NOTE(warning message)
#endif

Но это повторяет сообщение, и я уверен, что вы имели в виду не делать этого - и это громоздко; вы бы использовали его очень редко. Возможно, вам также придется иметь дело с другими компиляторами, кроме GCC (и я недостаточно знаком с MSVC, чтобы знать, как его надежно идентифицировать).

Было бы хорошо, если бы #warning были стандартизированы; это не стандартизировано в C99.

(Когда-то давно был такой вопрос о таких функциях, которые могли быть добавлены в C, и #warning возник там.)

См. Также: Переносимость директивы #warning препроцессора

3 голосов
/ 23 января 2009

Защитите их с помощью #if утверждений. Ищите символ, который определен одним компилятором, но не другим.

#ifdef _MSC_VER
#pragma NOTE(my warning here)
#else
#warning(my warning here)
#endif

Вроде некрасиво, но другого пути не вижу.

1 голос
/ 11 марта 2011

При желании вы можете добавить к вышеперечисленным решениям небольшую вещь (#pragma warning) перед тем, как ваш #pragma message:

#pragma warning()
#pragma message(" SOME USER WARNING - FILE LINE etc... ")

Эта небольшая надстройка генерирует реальное предупреждение и не выглядит плохо в окне VC. Например:

1>e:\proj\file.h(19) : warning C4615: #pragma warning : unknown user warning type
1> SOME USER WARNING - FILE LINE etc...
1>proj - 0 error(s), 1 warning(s)

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

Например, форма предупреждений слишком тихая (для меня, конечно).

1> SOME USER WARNING - FILE LINE etc..
1>proj - 0 error(s), 0 warning(s)

Впрочем, только небольшая косметика.

0 голосов
/ 24 марта 2018

Возможно иметь код, который работает везде и испускает пользовательские предупреждения о многих компиляторах, включая большинство компиляторов, использовать (GCC, clang, MSVC, Intel, ...).

Во-первых, мы должны различать предупреждения и информационные Сообщения. Я думаю, что единственное, что имеет смысл, это то, что если вы составить с фатальными предупреждениями ( например, , -Werror в GCC), предупреждениями должен привести к сбою компиляции, тогда как информационные сообщения не должны.

Как упоминается в оригинальном вопросе, MSVC 9.0+ поддерживает

#pragma message("Hello")

Несмотря на (ИМХО неудачное) имя, MSVC выдаст предупреждение здесь, не информационное сообщение. AFAICT нет никакого способа испустить информационное сообщение.

GCC 4.8+ и Intel поддерживают прагмы с предупреждающими сообщениями, что означает, что мы можем используйте препроцессор для их генерации:

#pragma GCC warning "Hello"

Обратите внимание, что начиная с версии 18 PGI не поддерживает такие предупреждения, даже хотя pgc ++ маскируется под версию GCC, которая должна (т.е. __GNUC__, __GNUC_MINOR__ и __GNUC_PATCHLEVEL__ устанавливает значения, которые указать GCC> = 4.8). Они есть 1020 * известно * вопроса. Чтобы обойти это, все еще позволяя некоторое будущее версию PGI, которая поддерживает те, чтобы работать должным образом, вы можете сделать что-то вроде:

#if defined(__PGI)
#  pragma diag_suppress 1675
#endif

К сожалению, я не думаю, что есть способ нажать / выдвинуть предупреждение стек для PGI, поэтому, если вы сделаете это, все последующие неизвестные прагмы будут быть тихо проигнорированным. Также имейте в виду, что #pragma message PGI молча игнорирует (он даже не выдаст предупреждение о прагма неизвестна).

Clang также поддерживает #pragma GCC warning (а также #pragma clang ...), но с 6.0 такие предупреждения на самом деле являются информационными (я подал ошибку). Я не уверен, когда была добавлена ​​поддержка, но версия Clang числа в любом случае довольно бесполезны (благодаря Apple, установив их что-то совершенно другое в их лязге распределение). К сожалению, нет __has_pragma функционального теста макрос, но мы можем временно отключить неизвестные предупреждения прагмы так что если компилятор не поддерживает прагму, он будет молча игнорируется вместо выдачи нежелательного предупреждения:

#if defined(__has_warning)
#  if __has_warning("-Wunknown-pragmas")
#    pragma clang diagnostic push
#    pragma clang diagnostic ignored "-Wunknown-pragmas"
#    pragma message "Hello"
#    pragma clang warning "Hello"
#    pragma clang diagnostic pop
#  endif
#endif

Конечно, это уродливо, но, по крайней мере, мы можем спрятать его за макросом.

Cray 5.0+ также имеет прагму для сообщений:

#pragma _CRI message "Hello"

У меня нет доступа к компилятору Cray, поэтому я не уверен о том, является ли это информационным или предупреждением. Если кто-то знает пожалуйста, прокомментируйте!

Собрав все вместе, я недавно добавил несколько макросов в Хедли чтобы справиться с этим, текущий версия выглядит так:

#if HEDLEY_HAS_WARNING("-Wunknown-pragmas")
#  define HEDLEY_MESSAGE(msg) \
  HEDLEY_DIAGNOSTIC_PUSH \
  _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") \
  HEDLEY_PRAGMA(message msg) \
  HEDLEY_DIAGNOSTIC_POP
#elif \
  HEDLEY_GNUC_VERSION_CHECK(4,4,0) || \
  HEDLEY_INTEL_VERSION_CHECK(16,0,0)
#  define HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(message msg)
#elif HEDLEY_CRAY_VERSION_CHECK(5,0,0)
#  DEFINE HEDLEY_MESSAGE(msg) HEDLEY_PRAGMA(_CRI message msg)
#else
#  define HEDLEY_MESSAGE(msg)
#endif

#if HEDLEY_HAS_WARNING("-Wunknown-pragmas")
#  define HEDLEY_WARNING(msg) \
  HEDLEY_DIAGNOSTIC_PUSH \
  _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") \
  HEDLEY_PRAGMA(clang warning msg) \
  HEDLEY_DIAGNOSTIC_POP
#elif \
  (HEDLEY_GNUC_VERSION_CHECK(4,8,0) && !defined(__PGI)) || \
  HEDLEY_INTEL_VERSION_CHECK(16,0,0)
#  define HEDLEY_WARNING(msg) HEDLEY_PRAGMA(GCC warning msg)
#elif HEDLEY_MSVC_VERSION_CHECK(15,0,0)
#  define HEDLEY_WARNING(msg) HEDLEY_PRAGMA(message(msg))
#else
#  define HEDLEY_WARNING(msg) HEDLEY_MESSAGE(msg)
#endif

Если вы не хотите использовать Hedley (это единственный публичный домен / заголовок CC0 только для такого рода вещей), вы можете заменить внутренние макросы без особых усилий. Если вы сделаете это, я бы посоветовал основывать ваш порт на репо Хедли, а не на этот ответ, так как я с большей вероятностью буду обновлять его.

...