Я знаю, что вопрос о GCC, но для людей, которые ищут, как это сделать в других и / или нескольких компиляторах ...
TL; DR
Возможно, вы захотите взглянуть на Hedley , который является одним из общедоступных заголовков C / C ++, который я написал и который делает для вас многое из этого. Я помещу краткий раздел о том, как использовать Хедли для всего этого в конце этого поста.
Отключение предупреждения
#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)
.
- ЗГУ: Есть
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
- лязг:
#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
это не единственное предупреждение, о котором знает Хедли, и не отключение предупреждений, которые может сделать Хедли, но, надеюсь, вы поняли идею.