16

在 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)

海合会有:

#warning(my warning here)

然而,MSVC(2003)在看到#warning并给出“致命错误 C1021:无效的预处理器命令'警告'”时会抛出一个合适的结果

我能做些什么呢?有没有办法让 GCC 识别 MSVC 警告或 MSVC 不会在 GCC 警告上引发错误?有什么我可以做的对两者都有效的吗?我可以让 GCC 警告我有关未知的编译指示,但这不是最理想的解决方案。

4

5 回答 5

15

我为这个问题找到的最佳解决方案是在一个公共标题中包含以下内容:

// 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")

贯穿整个代码而不是#warning

在 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

不是完美的,而是合理的妥协。

于 2009-12-16T01:11:03.593 回答
6

正如您现在发现的那样,#warning它不是标准功能,因此您不能将它与不支持它的编译器一起使用。如果您希望您的代码跨平台工作,那么您根本不会使用#warning- 或者至少不会在 MSVC 打算处理的代码中使用(它可以被预处理#ifdef或等效)。因此:

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

但这重复了这个信息,我敢肯定你有想过不要那样做——而且它很笨重;你只会很少使用它。您可能还需要处理除 GCC 之外的其他编译器(而且我对 MSVC 不够熟悉,不知道如何可靠地识别它)。

如果#warning标准化就好了;它在 C99 中没有标准化。

(很久以前,有一个关于可以添加到 C 并#warning出现在那里的功能的 SO 问题。)

另请参阅:#warning 预处理器指令的可移植性

于 2009-01-23T06:36:30.300 回答
3

用#if 语句保护它们。查找由一个编译器定义但不是另一个编译器定义的符号。

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

有点丑,但我没有看到其他方式。

于 2009-01-23T07:42:40.667 回答
2

可能有代码可以在任何地方工作,并在许多编译器上发出自定义警告,包括人们可能使用的大多数编译器(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 messagePGI 会默默地忽略它(它甚至不会生成关于 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 回购而不是这个答案,因为我更有可能保持最新。

于 2018-03-24T19:46:27.643 回答
1

如果您愿意,您可以在上述解决方案中添加一点东西 ( #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)

不过,只是小化妆品。

于 2011-03-11T18:56:06.570 回答