Re: static assertions

2009-12-21 Thread Hallvard B Furuseth
I wrote:
> 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.

Add a linked symbol, I mean - extern const char ber_pvt_assertion[1];

-- 
Hallvard


Re: static assertions

2009-12-21 Thread Hallvard B Furuseth
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.
Opinions?

>> 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 " 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_assertz():
  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));
becomes
  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.

-- 
Hallvard


Re: static assertions

2009-12-21 Thread Howard Chu

Hallvard B Furuseth wrote:

I think we should insert a number of static assertions in the
OpenLDAP code: Asserts that fail or succeed at compile time.
E.g. for the comment in config.c:bindkey[] (ITS#6419).

Like this - in include/ac/assert.h?
Or ldap_cdefs.h in case we want to use it in installed headers?

/* Declaration which tries to force a compile error if !cond */
#define ber_static_assert(cond) \
 LBER_V(LDAP_CONST char) ber_assertion[ber_assertz(cond) + 1]

/* Return 0, or if !cond try to force a compile error */
#define ber_assertz(cond) (sizeof(struct { \
 int ber_assert1[(cond) ? 9 : -9], ber_assert2:(cond) ? 9 : -9; })&&  0)

/* Usage: */
ber_static_assert(~0U>= 0xUL);   /* int = 32 bits or wider */
int foo(int i) { return i + ber_assertz(LDAP_SUCCESS == 0); }

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.

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.


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


--
  -- Howard Chu
  CTO, Symas Corp.   http://www.symas.com
  Director, Highland Sun http://highlandsun.com/hyc/
  Chief Architect, OpenLDAP  http://www.openldap.org/project/