Discussion:
[libvirt-users] [libvirt] ignore_value
gaosheng cui
2018-04-27 07:20:45 UTC
Permalink
Hi,using ignore_value in libvirt source code
to do function return value processing,but I
can’t understand about it,can you give me some tips?thanks very much!
Eric Blake
2018-04-27 16:15:53 UTC
Permalink
Post by gaosheng cui
Hi,using ignore_value in libvirt source code
to do function return value processing,but I
can’t understand about it,can you give me some tips?thanks very much!
Is your question about what ignore_value() does? It exists solely to
shut up compiler warnings about anything declared with
__attribute__((warn_unused_result)) (under our macro
ATTRIBUTE_RETURN_CHECK), in cases where we are intentionally ignoring
the return value (rather than assigning the value to a variable or using
the function call in an 'if' conditional, the way the compiler warning
would want us to do it).

Many of the uses in libvirt code base are things like this in
src/conf/domain_addr.c:

char *
virDomainPCIAddressAsString(virPCIDeviceAddressPtr addr)
{
char *str;

ignore_value(virAsprintf(&str, "%.4x:%.2x:%.2x.%.1x",
addr->domain,
addr->bus,
addr->slot,
addr->function));
return str;
}

We intentionally marked virAsprintf() as requiring the compiler to warn
if the return value is ignored, because in many cases, it really is a
bug if virAsprintf() failed (memory allocation or otherwise) and
returned NULL, but you didn't check it but blindly assumed that str is
non-NULL. But for this particular callsite,
virDomainPCIAddressAsString() is also documented as returning NULL on
failure, so we can ignore the return value of virAsprintf() and still
have correct semantics.

You can think of 'ignore_value(foo());' the same as '(void*)foo();',
except that the latter doesn't shut up all compilers. You only need to
use ignore_value() in situations where the compiler warns you, and even
then, only if you are sure that ignoring the value doesn't introduce
bugs - so using it also serves as a visual indicator to reviewers that
your choice to ignore the return value was intentional and should be
checked for accuracy.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
Eric Blake
2018-04-27 16:25:30 UTC
Permalink
Post by Eric Blake
You can think of 'ignore_value(foo());' the same as '(void*)foo();',
Typo, make that '(void)foo();'
Post by Eric Blake
except that the latter doesn't shut up all compilers.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
Eric Blake
2018-04-27 18:25:46 UTC
Permalink
Post by Eric Blake
Post by gaosheng cui
Hi,using ignore_value in libvirt source code
to do function return value processing,but I
can’t understand about it,can you give me some tips?thanks very much!
Is your question about what ignore_value() does?
Or, if your question is "Where is ignore_value defined", the answer is
that libvirt uses gnulib, and gnulib's "ignore-value.h" (imported during
./bootstrap if you are building from git; if you are building a release
tarball then it was already part of the tarball under lib/) contains
this definition:

/* Normally casting an expression to void discards its value, but GCC
versions 3.4 and newer have __attribute__ ((__warn_unused_result__))
which may cause unwanted diagnostics in that case. Use __typeof__
and __extension__ to work around the problem, if the workaround is
known to be needed. */
#if 3 < __GNUC__ + (4 <= __GNUC_MINOR__)
# define ignore_value(x) \
(__extension__ ({ __typeof__ (x) __x = (x); (void) __x; }))
#else
# define ignore_value(x) ((void) (x))
#endif
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
Loading...