MSVC equivalent of __attribute__ ((warn_unused_result))?

前端 未结 5 2209
旧时难觅i
旧时难觅i 2020-12-05 23:41

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

5条回答
  •  甜味超标
    2020-12-06 00:23

    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.

提交回复
热议问题