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

- 208,748
- 37
- 389
- 560
-
2Sure- it's called an exception. – Puppy Nov 19 '10 at 15:30
-
8@DeadMG: yes, unfortunately that's not quite as immediate as a compiler warning, and usually someone else has to fix the problem. – Paul R Nov 19 '10 at 15:34
5 Answers
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;
}

- 65,406
- 61
- 242
- 386
-
Many thanks for that - the original question was asked back in 2010, when obviously this didn't exist in MSVC, but it's good to know that it's now been added. I guess one can implement a macro which checks `_MSCVER` first and then uses `_Check_return_` if it's supported. – Paul R Mar 31 '14 at 08:42
-
I've now made this the accepted answer, as it is more up-to-date than the earlier answers. I've also added an answer of my own which includes a cross-platform macro with checks for MSVC version etc. Thanks again! – Paul R Mar 31 '14 at 10:35
-
1There's also [`_Must_inspect_result_`](https://learn.microsoft.com/en-us/visualstudio/code-quality/annotating-function-behavior?view=vs-2017) – diapir Sep 04 '18 at 22:30
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_RETURN int my_function(void); // declaration
// foo.c
CHECK_RETURN 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.

- 208,748
- 37
- 389
- 560
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.

- 1
- 1

- 99,718
- 31
- 186
- 324
-
-
@John + @Paul: http://www.microsoft.com/whdc/devtools/tools/annotations.mspx <-- The first example in the docx contains the `__checkReturn` annotation ;) – Billy ONeal Nov 19 '10 at 15:46
-
'Prefast' is now called 'Code Analysis for C/C++' - http://msdn.microsoft.com/en-us/library/d3bbz7tz.aspx – Steve Townsend Nov 19 '10 at 15:46
-
Thanks - this looks like it may do the job - we use cl and makefile builds so it should be easy enough to add a prefast option when building. – Paul R Nov 19 '10 at 16:23
-
1@Paul R - note that this will slow down your builds a lot, and also generate a lot of warnings that you may not care about. I would do this periodically instead of on every build, to avoid negative feedback on what's a valuable tool. – Steve Townsend Nov 19 '10 at 17:09
-
@Steve: thanks - noted - I'm not sure I'll be able to persuade everyone to install this stuff but may well make it an optional build step for those who choose to. – Paul R Nov 19 '10 at 21:30
-
1This is now called [_Check_return_](http://msdn.microsoft.com/en-us/library/jj159529.aspx) in the current Code Analysis implementation. – bfulgham Dec 16 '13 at 20:56
-
@bfulgham: Thanks for the info. I'm mostly off the VS stack these days. Could you please edit my answer with whatever new information you could provide? Or even supply your own answer. – John Dibling Dec 16 '13 at 21:05
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.

- 24,095
- 5
- 52
- 70
-
1Thanks - it's somewhat ironic that the platform that needs this the most is one whose compiler does not support it. – Paul R Nov 19 '10 at 15:31
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.

- 16,623
- 1
- 43
- 62