msvc和gcc上的用户警告?

时间:2009-01-23 05:07:35

标签: gcc visual-c++ user-warning

在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警告我关于未知的pragma,但这不是最理想的解决方案。

5 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:6)

正如您现在发现的那样,#warning不是标准功能,因此您不能将其用于不支持它的编译器。如果您希望代码跨平台工作,则根本不会使用#warning - 或者至少不会使用MSVC要处理的代码(可以由#ifdef预处理或同等学历)。因此:

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

但是重复了这个信息,我确信你不记得这样做 - 而且它很笨重;你很少使用它。您可能还需要处理除GCC之外的其他编译器(我对MSVC不够熟悉,不知道如何可靠地识别它)。

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

(很长一段时间以前,有关此类功能的SO问题可以添加到C和#warning。)

另请参阅:Portability of #warning preprocessor directive

答案 2 :(得分:3)

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

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

有点难看,但我没有看到另一种方式。

答案 3 :(得分: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)
然而,只有一个小化妆品。

答案 4 :(得分:0)

可能有代码可以在任何地方工作,并发出自定义 许多编译器的警告,包括大多数编译人员都可能 使用(GCC,clang,MSVC,Intel,......)。

首先,我们应该区分警告和信息 消息。我认为唯一有意义的是,如果你 使用致命警告编译(例如,GCC上的-Werror),警告 应该导致编译失败,而信息消息 不该'吨

正如最初的问题所提到的,MSVC 9.0+支持

#pragma message("Hello")

尽管(恕我直言,不幸)名字,MSVC将在这里发出警告, 不是信息性的消息。 AFAICT没有办法发出一个 信息性消息。

GCC 4.8+和英特尔支持警告消息编译指示,这意味着我们可以 使用预处理器生成它们:

#pragma GCC warning "Hello"

请注意,从版本18开始,PGI甚至不支持此类警告 虽然pgc ++伪装成GCC的一个版本(即它) 将__GNUC____GNUC_MINOR____GNUC_PATCHLEVEL__设置为值 表示GCC> = 4.8)。他们是 aware 这个问题。绕过这个,同时仍然允许一些未来 支持那些正常工作的PGI版本,你可以做到 类似的东西:

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

不幸的是,我认为没有办法推送/弹出警告 PGI的堆栈,所以如果你这样做,所有后续的未知编译指示都会 被默默地忽略。另外,请记住#pragma message是 PGI默默地忽略了它(它甚至不会产生警告 pragma未知)。

Clang还支持#pragma GCC warning(以及#pragma clang ...),但从6.0开始,此类警告实际上是信息性的(我已经提供了信息) 提交了一个错误)。我不确定何时添加支持,但是铿锵的版本 无论如何,数字都是无用的(感谢Apple将它们设置为 他们的铿锵声完全不同 分配)。遗憾的是,没有__has_pragma功能测试 宏,但我们可以暂时禁用未知的编译指示警告 如果编译器不支持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的编译器,所以我无法确定 关于它是信息还是警告。如果有人知道 anwser,请评论!

总而言之,我最近添加了一些宏 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仓库而不是这个答案,因为我更有可能让它保持最新。