Page MenuHomeFreeBSD

sys/cdefs.h: add __nodiscard annotation
ClosedPublic

Authored by ivy on Tue, May 6, 6:46 PM.
Tags
None
Referenced Files
F118727237: D50217.diff
Sun, Jun 1, 6:53 AM
F118688826: D50217.id155035.diff
Sat, May 31, 8:14 PM
F118662144: D50217.id155175.diff
Sat, May 31, 12:48 PM
Unknown Object (File)
Sat, May 31, 6:08 AM
Unknown Object (File)
Fri, May 30, 1:34 PM
Unknown Object (File)
Thu, May 29, 1:14 PM
Unknown Object (File)
Wed, May 28, 8:40 AM
Unknown Object (File)
Sun, May 25, 4:26 PM
Subscribers

Details

Summary

sys/cdefs.h: add __nodiscard annotation

__nodiscard adds the [[nodiscard]] attribute to a function, type or
constructor in C or C++, causing a value so marked to issue a compiler
warning if it is discarded (i.e., not used or assigned) other than by
casting it to void.

this replaces the existing __result_use_or_ignore_check, which has a
similar purpose but different semantics. since __nodiscard provides
more functionality (at least in GCC) and __result_use_or_ignore_check
only had a single user, remove __result_use_or_ignore_check.

[[nodiscard]] has been supported in C++ since C++17, but only in C since
C23; however, both LLVM and GCC implement it even in older language
versions, so it should always be available with a relatively modern
compiler.

for Clang, [[nodiscard]] in C is only available since LLVM 17, but we
can fall back to __attribute__((__warn_unused_result__)) which has the
same semantics and provides support back to (at least) LLVM 11.

GCC supports [[nodiscard]] in both C and C++ since at least GCC 11.
for GCC, we can't provide a fallback as the semantics of its
warn_unused_result are different, but since __result_use_or_ignore_check
isn't defined for GCC anyway, we don't lose anything here.

MFC after: 2 weeks

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

ivy requested review of this revision.Tue, May 6, 6:46 PM
sys/sys/cdefs.h
256

why churn the name?

sys/sys/cdefs.h
256
  1. they are not syntactically compatible.

valid:

int __result_use_or_ignore_check f()

not valid:

int __nodiscard f()
  1. the name __nodiscard has a clear and obvious meaning to anyone who knows C or C++ based on the standard attribute name. __result_use_or_ignore_check is hard to type, hard to read, and its meaning is not at all clear if you don't already know what it does.
sys/sys/cdefs.h
307

Do all the compilers we support understand the modern [[]] syntax or should we fall back to __attribute__ for older compilers?

sys/sys/cdefs.h
307

i tested GCC 11 (the oldest version in ports) and it supports [[nodiscard]] for both C and C++.

for GCC, we can't fall back to __attribute__ anyway because a) the semantics are different (you can't silence the warning with a cast to void), and b) GCC doesn't support warn_unused_result on types; it generates a -Wattributes warning which will break the build with -Werror. in practice this doesn't really matter since __result_use_or_ignore_check isn't defined for GCC anyway, so GCC only benefits by switching to __nodiscard.

for LLVM, i tested all versions currently in ports: 11, 12, 13, 14, 15, 16, 17, and 18. all versions support [[nodiscard]] in C++, but only LLVM 17 and later support it in C.

all versions of LLVM i tested support __warn_unused_result in C on both functions and types, with the same semantics as [[nodiscard]], so if we want to support LLVM 16 and older, i think we can a fallback here for LLVM, only in the C case.

for LLVM, add a fallback to warn_unused_result; this is semantically compatible
(unlike GCC's version) and is supported back to at least LLVM 11.

sys/sys/cdefs.h
256

fwiw, there is currently only one user of __result_use_or_ignore_check which is sys/systm.h, so we could just remove that entirely without creating much churn.

sys/sys/cdefs.h
256

Let's just go ahead and do that, then.

sys/sys/cdefs.h
256

shall i that in this diff or make a second one?

sys/sys/cdefs.h
256

might as well do it here

  • add doc in cdefs.9
  • remove result_use_or_ignore_check and replace uses of it with nodiscard
ivy edited the summary of this revision. (Show Details)

mention std::ignore in cdefs.9 for C++

This revision is now accepted and ready to land.Fri, May 9, 11:18 AM

For another commit: we should mark these up somehow so they're searchable with apropos. I think the relevant macros are (from mdoc(7)):

Semantic markup for function libraries
       Lb		function library (one argument)
       In		include	file (one argument)
       Fd		other preprocessor directive (>0 arguments)
       Ft		function type (>0 arguments)
       Fo, Fc		function block:	funcname
       Fn		function name: funcname	[argument ...]
       Fa		function argument (>0 arguments)
       Vt		variable type (>0 arguments)
       Va		variable name (>0 arguments)
       Dv		defined	 variable   or	 preprocessor	constant   (>0
				       arguments)
       Er		error constant (>0 arguments)
       Ev		environmental variable (>0 arguments)

No, apropos only searches man page titles (.Nm) and descriptions (.Nd).

share/man/man9/cdefs.9
124

This isn't wrong but the established style appears to be

.It Sy __nodiscard Ta Equivalent to the standard
share/man/man9/cdefs.9
120–121

preexisting issue

In D50217#1146689, @des wrote:

No, apropos only searches man page titles (.Nm) and descriptions (.Nd).

Sir, it is a great honor to inform you that apropos will search specific semantics if provided, e.g. apropos Fa=quantize or apropos Va=net.link.tap.

Well then apropos Sy=__nodiscard should work just fine.

In D50217#1146701, @des wrote:

Well then apropos Sy=__nodiscard should work just fine.

It does, but Sy is not a semantic markup, it's "bold", so it's not useful unless you already know we marked it up this way in the manual, vs if __nodiscard is a function name or something else then it would be more obvious and someone reading code could search for the function name __nodiscard.

This revision was automatically updated to reflect the committed changes.