MSVC 相当于 __attribute__ ((warn_unused_result))?

发布于 2024-10-03 00:57:57 字数 196 浏览 5 评论 0 原文

我发现 __attribute__ ((warn_unused_result)) 作为鼓励开发人员不要忽略函数返回的错误代码的一种方法非常有用,但我需要它与 MSVC 以及 gcc 和 gcc 一起使用- 兼容的编译器,例如 ICC。 Microsoft Visual Studio C/C++ 编译器是否有等效机制? (到目前为止,我已经尝试浏览 MSDN,但没有任何运气。)

I'm finding __attribute__ ((warn_unused_result)) to be very useful as a means of encouraging developers not to ignore error codes returned by functions, but I need this to work with MSVC as well as gcc and gcc-compatible compilers such as ICC. Do the Microsoft Visual Studio C/C++ compilers have an equivalent mechanism ? (I've tried wading through MSDN without any luck so far.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

℉絮湮 2024-10-10 00:57:57

它是_Check_return_。有关类似注释的示例,请参阅此处此处了解函数行为。自 MSVC 2012 起就受支持。

示例:

_Check_return_
int my_return_must_be_checked() {
    return 42;
}

It's _Check_return_. See here for examples of similar annotations and here for function behaviour. It's supported since MSVC 2012.

Example:

_Check_return_
int my_return_must_be_checked() {
    return 42;
}
哀由 2024-10-10 00:57:57

###MSVC 2012 及更高版本的更新

非常感谢 @Albert 指出,从 Visual Studio 2012 开始,在使用 SAL 静态代码分析时,MSVC 现在支持注释 _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_RESULT int my_function(void); // declaration

// foo.c

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

Note also that you'll need the `/analyze` (or `-analyze`) switch if compiling from the command line, or the equivalent if using the Visual Studio IDE. This also tends to slow the build down somewhat.

###UPDATE FOR MSVC 2012 AND LATER

Many thanks to @Albert for pointing out that MSVC now supports the annotation _Check_return_ as of Visual Studio 2012 when using SAL static code analysis. I'm adding this answer so that I can include a cross-platform macro which may be useful to others:

#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

Note that, unlike gcc et al, (a) MSVC requires annotations on both declaration and definition of a function, and (b) the annotation needs to be at the start of the declaration/definition (gcc allows either). So usage will typically need to be e.g.:

// foo.h

CHECK_RESULT int my_function(void); // declaration

// foo.c

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

Note also that you'll need the `/analyze` (or `-analyze`) switch if compiling from the command line, or the equivalent if using the Visual Studio IDE. This also tends to slow the build down somewhat.

时光暖心i 2024-10-10 00:57:57

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

Some editions of VisualStudio come packaged with a static analysis tool that used to be called PREFast (Now called simply "Code Analysis for C/C++"). PREFast uses annotations to mark up code. One of those annotations, MustCheck, does what you're looking for.

唐婉 2024-10-10 00:57:57

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

As far as I'm aware, the MS compilers don't have an equivalent pragma or attribute - the only "unused" type warning you can get is for variables when you have the optimizer turned on with the appropriate warning level.

蓝咒 2024-10-10 00:57:57

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

首先,GCC 从 3.4 开始仅支持 warn_unused_result。你可以
想要检查 __GNUC__ / __GNUC_MINOR__ 的值而不是
只是检查 __GNUC__ 是否已定义,尽管此时我已经
很难想象有人会使用 3.4 之前的 GCC 版本。

一些编译器支持 GCC 风格的函数属性,并且可能或
可能未定义 __GNUC__ 和朋友:

  • Clang(使用 __has_attribute(warn_unused_result) 进行检查),并且
    但基于它的编译器(emscripten、xlc 13+、armclang 等)
    AFAIK 它总是伪装成至少 GCC 4.2,所以你可能
    不需要显式检查。
  • Intel 并不总是定义 __GNUC__(请参阅 -no-gcc 标志)。我
    不知道他们什么时候开始支持它(他们的文档是
    严重缺乏),但我知道 16.0+ 是安全的。
  • TI 8.0+ 支持
  • TI 7.3+ 在传递 --gcc 时支持;
    __TI_GNU_ATTRIBUTE_SUPPORT__ 将在此时定义。
  • Oracle Developer Studio 12.6+ 在 C++ 模式下支持它,但不支持
    C。
  • PGI 在 C++ 模式下支持它。 AFAICT 它没有记录,所以我不是
    确定它是什么时候添加的(#1650-D),但它肯定存在
    在 17.10+ 中。它在 C 模式下被默默地忽略,希望他们会
    有一天实施它。

此外,C++17 添加了 [[nodiscard]] 属性。对于以下版本
GCC/clang 在 C++17 模式下支持 [[nodiscard]] 您也可以使用
[[gnu::nodiscard]] 在 C++11 及更高模式中,但如果您隐藏
无论如何,它在宏后面我看不出有理由这样做而不是
只需使用 __attribute__((__warn_unused_result__)) 。

放在一起,HEDLEY_WARN_UNUSED_RESULT 宏“https://nemequ.github.io/hedley/” rel="nofollow noreferrer">Hedley 看起来像:

#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 宏,然后
如果你不想使用,复制逻辑不会太麻烦
Hedley(属于公共领域/CC0)。如果您选择这样做,您应该
可能会将您的移植基于存储库中的版本,因为我的版本要少得多
可能会记得让这个答案保持最新
信息。

I think the SAL annotation which others have mentioned is the right
answer for MSVC, but I'm guessing some people will be interested in
more portability than just MSVC, GCC, and GCC-compatible compliers,
so…

First off, GCC only supports warn_unused_result since 3.4. You may
want to check the values of __GNUC__ / __GNUC_MINOR__ instead of
just checking if __GNUC__ is defined, although at this point I have
trouble imagining anyone using a version of GCC older than 3.4.

Several compilers support the GCC-style function attribute, and may or
may not define __GNUC__ and friends:

  • Clang (check with __has_attribute(warn_unused_result)), and
    compilers based on it (emscripten, xlc 13+, armclang, etc.), though
    AFAIK it always masquerades as at least GCC 4.2, so you probably
    don't need an explicit check.
  • Intel doesn't always define __GNUC__ (see the -no-gcc flag). I
    don't know when they started supporting it (their documentation is
    severely lacking), but I know 16.0+ is safe.
  • TI 8.0+ supports it
  • TI 7.3+ supports it when --gcc is passed;
    __TI_GNU_ATTRIBUTE_SUPPORT__ will be defined when it is.
  • Oracle Developer Studio 12.6+ supports it in C++ mode, though not
    C
    .
  • PGI supports it in C++ mode. AFAICT it's undocumented so I'm not
    sure when it was added (it's #1650-D), but it's definitely present
    in 17.10+. It's silently ignored in C mode, hopefully they'll
    implement it some day.

Additionally, C++17 adds a [[nodiscard]] attribute. For versions of
GCC/clang which support [[nodiscard]] in C++17 mode you can also use
[[gnu::nodiscard]] in C++11 and greater mode, but if you're hiding
it behind a macro anyways I don't see a reason to do so instead of
just using __attribute__((__warn_unused_result__)).

Putting it together, there is a HEDLEY_WARN_UNUSED_RESULT macro in Hedley which looks like:

#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

You should be able to strip out the internal Hedley macros and just
copy the logic without too much trouble if you don't want to use
Hedley (it's public domain / CC0). If you choose to do so you should
probably base your port off the version in the repo as I'm far less
likely to remember to keep this answer up to date with new
information.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文