MSVC相当于__attribute __((warn_unused_result))?

时间:2010-11-19 15:12:12

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

我发现__attribute__ ((warn_unused_result))非常有用,可以鼓励开发人员不要忽略函数返回的错误代码,但是我需要这个来处理MSVC以及gcc和gcc兼容的编译器,比如ICC。 Microsoft Visual Studio C / C ++编译器是否具有等效机制? (到目前为止,我已经尝试过通过MSDN而没有任何运气。)

5 个答案:

答案 0 :(得分:13)

这是_Check_return_。有关类似注释的示例,请参阅here;有关函数行为,请参阅here。自MSVC 2012以来,它得到了支持。

示例:

_Check_return_
int my_return_must_be_checked() {
    return 42;
}

答案 1 :(得分:8)

2012年及以后的MSVC更新

非常感谢@Albert指出,当使用SAL静态代码分析时,MSVC现在支持Visual Studio 2012中的注释_Check_return_。我正在添加这个答案,以便我可以包含一个对其他人有用的跨平台宏:

#if defined(__GNUC__) && (__GNUC__ >= 4)
#define CHECK_RESULT __attribute__ ((warn_unused_result))
#elif defined(_MSC_VER) && (_MSC_VER >= 1700)
#define CHECK_RESULT _Check_return_
#else
#define CHECK_RESULT
#endif

请注意,与gcc 不同,(a)MSVC要求对函数的声明定义进行注释,并且(b)注释需要在声明/定义的开头(gcc允许)。因此通常需要使用例如:


// foo.h

CHECK_RETURN int my_function(void); // declaration


// foo.c

CHECK_RETURN int my_function(void)  // definition
{
    return 42;
}


另请注意,如果从命令行进行编译,则需要/analyze(或-analyze)开关,如果使用Visual Studio IDE,则需要等效。这也有助于减缓构建速度。

答案 2 :(得分:5)

VisualStudio的某些版本附带了一个静态分析工具,以前称为PREFast(现在简称为“C / C ++代码分析”)。 PREFast使用注释来标记代码。其中一个注释MustCheck可以满足您的需求。

答案 3 :(得分:3)

据我所知,MS编译器没有等效的编译指示或属性 - 当您使用适当的警告级别打开优化器时,可以获得的唯一“未使用”类型警告是变量。

答案 4 :(得分:1)

我认为其他人提到的SAL注释是正确的 回答MSVC,但我猜测有些人会对此感兴趣 比MSVC,GCC和GCC兼容的编译器更具可移植性, 所以...

首先,自3.4以来,GCC仅支持warn_unused_result。你可能 想要检查__GNUC__ / __GNUC_MINOR__的值,而不是 只是检查是否定义了__GNUC__,尽管此时我已经定义了__GNUC__ 很难想象有人使用的是超过3.4的GCC版本。

有几个编译器支持GCC样式的函数属性,可能或 可能无法定义__has_attribute(warn_unused_result)和朋友:

  • Clang(与__GNUC__核对),和 但是,基于它的编译器(emscripten,xlc 13+,armclang等) AFAIK它总是伪装成至少GCC 4.2,所以你可能 不要需要明确检查。
  • 英特尔并不总是定义-no-gcc(请参阅__TI_GNU_ATTRIBUTE_SUPPORT__标志)。一世 不知道他们什么时候开始支持它(他们的文件是 严重缺乏),但我知道16.0+是安全的。
  • TI 8.0+支持
  • TI 7.3+支持--gcc通过时; [[nodiscard]]将被定义。
  • Oracle Developer Studio 12.6+在C ++模式下支持though not C
  • PGI在C ++模式下支持它。 AFAICT它没有记录,所以我不是 确定它何时被添加(它的#1650-D),但它肯定存在 在17.10+。它在C模式下被默默地忽略了,希望他们能够这样做 有一天实施它。

此外,C ++ 17添加了[[nodiscard]]属性。对于版本 在C ++ 17模式下支持[[gnu::nodiscard]]的GCC / clang也可以使用 在C ++ 11及更高版本模式下__attribute__((__warn_unused_result__)),但如果您要隐藏 无论如何,它在宏观背后我没有看到这样做的理由而不是 只使用#if defined(__cplusplus) && (__cplusplus >= 201703L) # define HEDLEY_WARN_UNUSED_RESULT [[nodiscard]] #elif \ HEDLEY_GNUC_HAS_ATTRIBUTE(warn_unused_result,3,4,0) || \ HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \ HEDLEY_TI_VERSION_CHECK(8,0,0) || \ (HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ (HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ HEDLEY_PGI_VERSION_CHECK(17,10,0) # define HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) #elif defined(_Check_return_) /* SAL */ # define HEDLEY_WARN_UNUSED_RESULT _Check_return_ #else # define HEDLEY_WARN_UNUSED_RESULT #endif

将它放在一起,HEDLEY_WARN_UNUSED_RESULT中有一个Hedley宏看起来像:

document.querySelector('a[rel="Spanish"]')

你应该能够剥离内部的Hedley宏而且只是 如果你不想使用,复制逻辑没有太多麻烦 Hedley(它的公共领域/ CC0)。如果你选择这样做,你应该这样做 可能是基于你在回购中的版本的端口,因为我更少 可能要记住用新的答案保持这个答案是最新的 信息。