Я знаю, что вопрос о GCC, но для людей, которые ищут, как это сделать в других и / или нескольких компиляторах ...
TL; DR
Возможно, вы захотите взглянутьпо адресу Hedley , который является единственным общедоступным заголовком C / C ++, который я написал, который делает lot этих вещей для вас.В конце этого поста я расскажу о том, как использовать Хедли для всего этого.
Отключение предупреждения
#pragma warning (disable: …)
имеет эквиваленты в большинстве компиляторов:
- MSVC:
#pragma warning(disable:4996)
- GCC:
#pragma GCC diagnostic ignored "-W…"
, где многоточие является названием предупреждения; например , #pragma GCC diagnostic ignored "-Wdeprecated-declarations
. - лязг:
#pragma clang diagnostic ignored "-W…"
.Синтаксис в основном такой же, как в GCC, и многие имена предупреждений совпадают (хотя многие не совпадают). - Компилятор Intel C: используйте синтаксис MSVC, но имейте в виду, что номера предупреждений полностьюразные.Пример:
#pragma warning(disable:1478 1786)
. - PGI: существует
diag_suppress
прагма: #pragma diag_suppress 1215,1444
- TI: существует прагма
diag_suppress
с тем же синтаксисом (но с разными номерами предупреждений!) как PGI: pragma diag_suppress 1291,1718
- Oracle Developer Studio (suncc): существует прагма
error_messages
.Досадно, что предупреждения для компиляторов C и C ++ различны.Оба они отключают в основном одни и те же предупреждения: - C:
#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
- C ++:
#pragma error_messages(off,symdeprecated,symdeprecated2)
- IAR: также используется
diag_suppress
как PGI и TI, но синтаксис другой.Некоторые из номеров предупреждений те же, но другие разошлись: #pragma diag_suppress=Pe1444,Pe1215
- Pelles C: аналогично MSVC, хотя опять-таки цифры разные
#pragma warn(disable:2241)
ДляДля большинства компиляторов часто хорошей идеей является проверка версии компилятора, прежде чем пытаться отключить его, в противном случае вы просто получите другое предупреждение.Например, в GCC 7 добавлена поддержка предупреждения -Wimplicit-fallthrough
, поэтому, если вы заботитесь о GCC до 7, вы должны сделать что-то вроде
#if defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Для clang и компиляторов на основе clang, таких как более новые версии XL C/ C ++ и armclang, вы можете проверить, знает ли компилятор о конкретном предупреждении, используя макрос __has_warning()
.
#if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
Конечно, вы также должны проверить, существует ли макрос __has_warning()
:
#if defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
# endif
#endif
У вас может возникнуть соблазн сделать что-то вроде
#if !defined(__has_warning)
# define __has_warning(warning)
#endif
Так что вы можете использовать __has_warning
немного легче.Clang даже предлагает нечто подобное для макроса __has_builtin()
в своем руководстве. Не делайте этого .Другой код может проверить на __has_warning
и вернуться к проверке версий компилятора, если он не существует, и если вы определите __has_warning
, вы нарушите их код.Правильный способ сделать это - создать макрос в вашем пространстве имен.Например:
#if defined(__has_warning)
# define MY_HAS_WARNING(warning) __has_warning(warning)
#else
# define MY_HAS_WARNING(warning) (0)
#endif
Затем вы можете делать такие вещи, как
#if MY_HAS_WARNING(warning)
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Нажатие и выталкивание
Многие компиляторы также поддерживают способ отправки и вставки предупреждений в стек,Например, это отключит предупреждение в GCC для одной строки кода, а затем вернет его в прежнее состояние:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop
Конечно, между компиляторами нет большого согласия относительно синтаксиса:
- GCC 4.6+:
#pragma GCC diagnostic push
/ #pragma GCC diagnostic pop
- clang:
#pragma clang diagnostic push
/ #pragma diagnostic pop
- Intel 13+ (и, вероятно, раньше):
#pragma warning(push)
/ #pragma warning(pop)
- MSVC 15+ (VS 9.0 / 2008):
#pragma warning(push)
/ #pragma warning(pop)
- ARM 5.6+:
#pragma push
/ #pragma pop
- TI 8.1+:
#pragma diag_push
/ #pragma diag_pop
- Pelles C 2.90+ (и, возможно, раньше):
#pragma warning(push)
/ #pragma warning(pop)
Если память служит, дляВ некоторых очень старых версиях GCC (например, 3.x, IIRC) прагмы push / pop должны были вне функции.
Скрывать кровавые детали
ДляВ большинстве компиляторов можно скрыть логику за макросами, используя _Pragma
, который был представлен в C99.Даже в режиме без C99 большинство компиляторов поддерживают _Pragma
;большое исключение - MSVC, у которого есть собственное ключевое слово __pragma
с другим синтаксисом.Стандарт _Pragma
принимает строку, версия Microsoft не:
#if defined(_MSC_VER)
# define PRAGMA_FOO __pragma(foo)
#else
# define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO
Примерно эквивалентно, после предварительной обработки,
#pragma foo
Это позволяет нам создавать макросы, чтобы мы могли писатькод типа
MY_DIAGNOSTIC_PUSH
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP
И скрыть все уродливые проверки версий в определениях макросов.
Легкий путь: Хедли
Теперь, когда вы понимаете механику того, как делать подобные вещи, сохраняя свой код в чистоте, вы понимаете, что делает один из моих проектов, Хедли . Вместо того, чтобы копаться в тоннах документации и / или устанавливать столько версий компиляторов, сколько вы можете протестировать, вы можете просто включить Hedley (это единственный общедоступный заголовок C / C ++) и покончить с этим. Например:
#include "hedley.h"
HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
Отключит предупреждение о вызове устаревшей функции в GCC, clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles и, возможно, других (возможно, я не буду обновлять этот ответ, когда обновляю Хедли). И на компиляторах, которые, как известно, не работают, макросы будут предварительно обработаны, и ваш код продолжит работать с любым компилятором. Конечно, HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
- не единственное предупреждение, о котором знает Хедли, и не отключение предупреждений, которые может сделать Хедли, но, надеюсь, вы поняли идею.