【问题标题】:user warnings on msvc AND gcc?msvc 和 gcc 上的用户警告?
【发布时间】:2009-01-23 05:07:34
【问题描述】:

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

GCC 有:

#warning(my warning here)

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

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

【问题讨论】:

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


【解决方案1】:

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

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

不完美,但合理的妥协。

【讨论】:

  • Markdown 似乎不想为我工作,但我想补充一点,如果您只支持与 C99 和 VS2008+ 兼容的 GCC 版本,您可以使用 GCC 的 __Pragma 关键字(例如: __Pragma(message("WARNING: " exp)))和 MSVC 的 __pragma 关键字(例如:__pragma(message(FILE_LINE_LINK "WARNING: " exp)))可以进一步缩短它。我假设 VS2008 是支持的最低版本,因为 first version on MSDN 的文档引用了这个关键字。
  • 如果在消息的开头(FILE_LINE_LINK 之后)打印“警告:”而不是“警告:”,它甚至会作为警告出现在错误列表中!
  • 很遗憾,MSVC 现在不喜欢它。除了使用#pragma message(…)之外,现在似乎没有可移植的警告方式。
【解决方案2】:

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

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

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

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

(很久以前,有一个关于可以添加到 C 和 #warning 的功能的 SO 问题。)

另请参阅:Portability of #warning preprocessor directive

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 你在我编辑答案并添加逆向测试时添加了这个......我猜_MSC_VER__GNUC__ 的对应物!谢谢。
    • _MSC_VER 不仅声明您使用的是 Microsoft C++,它还定义了您使用的版本。
    • 通常 predef.sourceforge.net 是一个很好的资源,用于查找编译器、操作系统、库等的识别信息。
    【解决方案4】:

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

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

    正如原始问题所述,MSVC 9.0+ 支持

    #pragma message("Hello")
    

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

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

    #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 开始,此类警告实际上是信息性的(我已经 提交了一个错误)。我不确定何时添加了支持,但 clang 的版本 无论如何数字都非常无用(感谢Apple将它们设置为 在他们的铿锵声中完全不同的东西 分配)。不幸的是,没有__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 的编译器,所以我不能确定 关于它是信息还是警告。如果有人知道 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 回购而不是这个答案,因为我更有可能保持最新。

    【讨论】:

      【解决方案5】:

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

      不过,只是个小化妆品。

      【讨论】:

      • 强制 MSVC 编译器计算/显示实际警告的更简单方法是在输出消息中添加文本 ": warning: "
      猜你喜欢
      • 2015-09-15
      • 2021-07-17
      • 2011-09-20
      • 1970-01-01
      • 2021-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多