svn commit: r358392 - head/share/man/man9

Mark Millard marklmi at yahoo.com
Fri Feb 28 04:17:47 UTC 2020


[Ignoring llvm-project and libstdc++, I only find
about 24 other instances of "static_assert".]

On 2020-Feb-27, at 19:03, Mark Millard <marklmi at yahoo.com> wrote

> On 2020-Feb-27, at 16:37, John Baldwin <jhb at FreeBSD.org> wrote:
> 
>> On 2/27/20 2:45 PM, Mark Millard wrote:
>>> John Baldwin jhb at FreeBSD.org wrote on
>>> Thu Feb 27 16:55:01 UTC 2020:
>>> 
>>>> On 2/27/20 7:30 AM, Warner Losh wrote:
>>>>> Author: imp
>>>>> Date: Thu Feb 27 15:30:13 2020
>>>>> New Revision: 358392
>>>>> URL: https://svnweb.freebsd.org/changeset/base/358392
>>>>> 
>>>>> Log:
>>>>> _Static_assert is to be preferred to CTASSERT.
>>>>> 
>>>>> Document the existing prefernce that _Static_assert be used in preference to the
>>>>> old CTASSERT we used to use for compile time assertions.
>>>> 
>>>> Actually, I think what we want to use is static_assert().  The intention in
>>>> userland C is that _Static_assert() is an internal keyword and <assert.h>
>>>> adds static_assert() as an alias, similar to <stdalign.h> defining alignas,
>>>> etc.  I think what we should do for the kernel is have <sys/systm.h> define
>>>> map static_assert to _Static_assert and replace existing _Static_assert
>>>> usage with the proper spelling.
>>>> 
>>> 
>>> Be warned static_assert is a C++ keyword as of C++11.
>>> 
>>> c++11 added: static_assert(bool_constexpr,message)
>>> c++17 added: static_assert(bool_constexpr)
>>> 
>>> C11 added _Static_assert(expression,message)
>>> C2x gets  _Static_assert(expression)
>>> 
>>> C11 added "#define static_assert _Static_assert" to <assert.h>
>>> 
>>> It makes for a bit of a mess in code to be allowed
>>> to be processed by both C and C++.
>>> 
>>> The wording may need to specify enough to tell what to
>>> do for such code and the headers may need logic to
>>> cause that context to exist across both languages
>>> when the header is allowed for both.
>> 
>> The intent of the C11 changes is to permit equivalent use of static_assert()
>> in both languages.  The #define in <assert.h> is guarded to not kick in for
>> C++.
> 
> Ahh. I had vague memories of past oddities in the area
> that I was involved in. So I looked and found (in head
> -r3578132 source) :
> 
> # more /usr/src/sys/sys/cdefs.h
> . . .
> #if !__has_extension(c_static_assert)
> #if (defined(__cplusplus) && __cplusplus >= 201103L) || \
>    __has_extension(cxx_static_assert)
> #define _Static_assert(x, y)    static_assert(x, y)
> #elif __GNUC_PREREQ__(4,6) && !defined(__cplusplus)
> /* Nothing, gcc 4.6 and higher has _Static_assert built-in */
> #elif defined(__COUNTER__)
> #define _Static_assert(x, y)    __Static_assert(x, __COUNTER__)
> #define __Static_assert(x, y)   ___Static_assert(x, y)
> #define ___Static_assert(x, y)  typedef char __assert_ ## y[(x) ? 1 : -1] \
>                                __unused
> #else
> #define _Static_assert(x, y)    struct __hack
> #endif
> #endif
> . . .
> 
> # more /usr/include/assert.h
> . . .
> /*
> * Static assertions.  In principle we could define static_assert for
> * C++ older than C++11, but this breaks if _Static_assert is
> * implemented as a macro.
> *
> * C++ template parameters may contain commas, even if not enclosed in
> * parentheses, causing the _Static_assert macro to be invoked with more
> * than two parameters.
> */
> #if __ISO_C_VISIBLE >= 2011 && !defined(__cplusplus)
> #define static_assert   _Static_assert
> #endif
> . . .
> 
> So one can define a _Static_assert macro, sometimes in terms of
> static_assert, and the other sometimes defines a static_assert
> macro in terms of _Static_assert.
> 
> Messy, but possibly localized.
> 
> That prompted a more general grep:
> 
> # grep -r "define[     _]*[Ss]tatic_assert" /usr/src/* | more
> /usr/src/contrib/llvm-project/libcxx/include/__config:# define static_assert(...) _Static_assert(__VA_ARGS__)
> /usr/src/contrib/llvm-project/libunwind/src/config.h:  #define static_assert(__b, __m) \
> /usr/src/include/assert.h: * Static assertions.  In principle we could define static_assert for
> /usr/src/include/assert.h:#define       static_assert   _Static_assert
> /usr/src/sys/sys/cdefs.h:#define        _Static_assert(x, y)    static_assert(x, y)
> /usr/src/sys/sys/cdefs.h:#define        _Static_assert(x, y)    __Static_assert(x, __COUNTER__)
> /usr/src/sys/sys/cdefs.h:#define        __Static_assert(x, y)   ___Static_assert(x, y)
> /usr/src/sys/sys/cdefs.h:#define        ___Static_assert(x, y)  typedef char __assert_ ## y[(x) ? 1 : -1] \
> /usr/src/sys/sys/cdefs.h:#define        _Static_assert(x, y)    struct __hack
> /usr/src/usr.bin/dtc/util.hh:#define static_assert(x, y) ((void)0)
> 
> So not much else.

Just an FYI: Looks like static_assert is little used (outside
llvm-project and libstdc++):

# grep -r "\<static_assert\>" /usr/src/* | grep -v llvm-project | grep -v "libstdc\+\+" | more
/usr/src/contrib/googletest/googlemock/include/gmock/gmock-matchers.h:      static_assert(
/usr/src/contrib/googletest/googlemock/include/gmock/gmock-matchers.h:    static_assert(sizeof...(Args) > 0, "Must have at least one matcher.");
/usr/src/contrib/googletest/googlemock/docs/DesignDoc.md:Google Test (the name is chosen to match `static_assert` in C++0x).
/usr/src/contrib/googletest/googletest/include/gtest/internal/gtest-port.h:# define GTEST_COMPILE_ASSERT_(expr, msg) static_assert(expr, #msg)
/usr/src/contrib/googletest/googletest/include/gtest/internal/gtest-port.h:// (In C++11, we simply use static_assert instead of the following)
/usr/src/contrib/bsnmp/snmpd/trans_inet.c:static_assert(offsetof(struct port_sock, input) == 0,
/usr/src/contrib/bsnmp/snmpd/trans_inet.c:static_assert(offsetof(struct inet_port, tport) == 0,
/usr/src/contrib/libcxxrt/guard.cc:static_assert(sizeof(guard_t) == sizeof(uint64_t), "");
/usr/src/contrib/ofed/libibumad/umad.c:static_assert(sizeof(struct ib_user_mad_reg_req) == IOCPARM_LEN(IB_USER_MAD_REGISTER_AGENT),
/usr/src/contrib/ofed/libibumad/umad.c:static_assert(sizeof(struct ib_user_mad_reg_req2) == IOCPARM_LEN(IB_USER_MAD_REGISTER_AGENT2),
/usr/src/include/assert.h: * Static assertions.  In principle we could define static_assert for
/usr/src/include/assert.h:#define       static_assert   _Static_assert
/usr/src/sys/sys/cdefs.h:#define        _Static_assert(x, y)    static_assert(x, y)
/usr/src/sys/contrib/zstd/contrib/pzstd/utils/FileSystem.h:  static_assert(false, "No POSIX stat() support.");
/usr/src/sys/contrib/zstd/contrib/pzstd/utils/FileSystem.h:  static_assert(false, "NO POSIX stat() support.");
/usr/src/usr.bin/dtc/HACKING:The code also makes use of `static_assert()` to track compile-time invariants.
/usr/src/usr.bin/dtc/util.hh:#ifndef static_assert
/usr/src/usr.bin/dtc/util.hh:#define static_assert(x, y) ((void)0)
/usr/src/usr.bin/dtc/util.hh:   static_assert(sizeof(T) > 1,
/usr/src/usr.sbin/bhyve/task_switch.c:static_assert(sizeof(struct tss32) == 104, "compile-time assertion failed");
/usr/src/usr.sbin/bhyve/pci_emul.h:static_assert(sizeof(struct msicap) == 14, "compile-time assertion failed");
/usr/src/usr.sbin/bhyve/pci_emul.h:static_assert(sizeof(struct msixcap) == 12, "compile-time assertion failed");
/usr/src/usr.sbin/bhyve/pci_emul.h:static_assert(sizeof(struct pciecap) == 60, "compile-time assertion failed");
/usr/src/usr.sbin/syslogd/syslogd.c:                    static_assert(sizeof(f->f_prevline) == sizeof(saved),

_Static_assert looks to be far more common. (Too long
to list here.)


===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)



More information about the svn-src-head mailing list