[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: static assertions

Howard Chu writes:
>Hallvard B Furuseth wrote:

[Rearranging a little]

> Since this is all ber/LBER, it should go in an lber_* header file, not 
> ac/assert.h.

OK.  I guess that means
    lber_pvt.h: ber_pvt_assertz(), ber_pvt_static_assert()
since on second thought I don't see much need to export it in installed
headers.  After all there's nothing BER/LDAP-specific about asserts.

>> liblber will need a dummy variable 'const char ber_assertion[1];'.
>> We can drop that if anyone dislikes it: ber_static_assert() can take
>> an assertion_name parameter and declare a typedef based on that name.
>> Or it can generate a name from __LINE__.  Then we can have only one
>> static assert per line, which matters for macros but little else.

Also the __LINE__ variant must not be used in headers, since then we can
have name clashes between assertions in different .h/.c files:-(

> You could avoid the naming issue by just enclosing the body in a block {}.
> I'm assuming we only need this inside functions, and not at file scope.

We don't need it, but it's cleaner with the assertion near the code it
asserts about - and we do have file-scope assumptions like "<file-scope
array X> has length Y", e.g. relay_fail_modes[] in back-relay/op.c.

However ber_pvt_static_assert() is just a convenience wrapper around
  ber_pvt_static_assert(cond);                can be replaced with
  (void) ber_pvt_assertz(cond);               for an {} assert, and
  enum { some_name = ber_pvt_assertz(cond) }; for a declaration assert.

So whatever we do for ber_pvt_static_assert(), if it doesn't fit the
needs of some piece of code it can use one of the latter forms.
I prefer it as a declaration since that helps with the ugliest (and
longest) syntax.

I too prefer to avoid a name parameter, so if a linker symbol is a
problem I suggest the __LINE__ variant for now.  We can also add a
symbol the macro can use in the future, but not use it yet to keep
compatibility with existing binaries.

BTW, yet another trick is to stuff the assertion into the prototype
of an existing function:
  LBER_F(void) ber_pvt_sb_buf_init LDAP_P((Sockbuf_Buf *buf));
  LBER_F(void) ber_pvt_sb_buf_init(Sockbuf_Buf buf[assertz expression]);
which is supposed to be equivalent - and we already require ISO C
for internal files.