可能有代码可以在任何地方工作,并在许多编译器上发出自定义警告,包括人们可能使用的大多数编译器(GCC、clang、MSVC、Intel ......)。
首先,我们应该区分警告和信息性消息。我认为唯一有意义的是,如果您使用致命警告进行编译(例如,-Werror
在 GCC 上),警告应该会导致编译失败,而信息性消息不应该。
正如原始问题所提到的,MSVC 9.0+ 支持
#pragma message("Hello")
尽管(恕我直言,不幸的)名称,MSVC 会在此处发出警告,而不是信息性消息。AFAICT 没有办法发出信息性消息。
GCC 4.8+ 和 Intel 支持警告消息 pragma,这意味着我们可以使用预处理器来生成它们:
#pragma GCC warning "Hello"
请注意,从版本 18 开始,PGI 不支持此类警告,即使 pgc++ 伪装成应该的 GCC 版本(即,它将 、 和 设置__GNUC__
为__GNUC_MINOR__
指示__GNUC_PATCHLEVEL__
GCC >= 4.8 的值)。他们
意识到
了这个问题。为了解决这个问题,同时仍然允许某些支持这些功能的 PGI 未来版本正常工作,您可以执行以下操作:
#if defined(__PGI)
# pragma diag_suppress 1675
#endif
不幸的是,我认为没有办法推送/弹出 PGI 的警告堆栈,所以如果你这样做,所有后续的未知 pragma 都将被默默地忽略。另外,请记住#pragma message
PGI 会默默地忽略它(它甚至不会生成关于 pragma 未知的警告)。
Clang 也支持#pragma GCC warning
(以及#pragma clang
...
),但从 6.0 开始,此类警告实际上是信息性的(我已经提交了一个错误)。我不确定何时添加了支持,但无论如何,clang 的版本号几乎没有用(感谢 Apple 在其 clang 发行版中将它们设置为完全不同的东西)。不幸的是,没有__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 的编译器,所以我不能确定它是信息性的还是警告性的。如果有人知道答案,请发表评论!
综上所述,我最近在
Hedley中添加了一些宏来处理这个问题,当前版本如下所示:
#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 标头,仅用于此类事情),您可以轻松替换内部宏。如果你这样做,我建议将你的端口基于 Hedley 回购而不是这个答案,因为我更有可能保持最新。