From 2255b865130df1feadea60779babd6889285186e Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 5 Apr 2011 23:45:10 -0700 Subject: [PATCH] verify: use _Static_assert if available * lib/verify.h (HAVE__STATIC_ASSERT): New macro. (verify_true, verify): Use it if available. This generates better diagnostics with GCC 4.6.0 and later. --- ChangeLog | 7 +++++++ lib/verify.h | 43 ++++++++++++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7ac579802..eee95090a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-04-06 Paul Eggert + + verify: use _Static_assert if available + * lib/verify.h (HAVE__STATIC_ASSERT): New macro. + (verify_true, verify): Use it if available. This generates better + diagnostics with GCC 4.6.0 and later. + 2011-04-05 Bruno Haible Remove leftover generated .h files after config.status changed. diff --git a/lib/verify.h b/lib/verify.h index 5e91abdbe..6c1f8c9e8 100644 --- a/lib/verify.h +++ b/lib/verify.h @@ -20,6 +20,17 @@ #ifndef VERIFY_H # define VERIFY_H 1 +/* Define HAVE__STATIC_ASSERT to 1 if _Static_assert works as per the + C1X draft N1548 section 6.7.10. This is supported by GCC 4.6.0 and + later, and its use here generates easier-to-read diagnostics when + verify (R) fails. + + For now, use this only with GCC. Eventually whether _Static_assert + works should be determined by 'configure'. */ +# if 4 < __GNUC__ || (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) +# define HAVE__STATIC_ASSERT 1 +# endif + /* Each of these macros verifies that its argument R is nonzero. To be portable, R should be an integer constant expression. Unlike assert (R), there is no run-time overhead. @@ -31,7 +42,12 @@ Symbols ending in "__" are private to this header. - The code below uses several ideas. + If _Static_assert works, verify (R) uses it directly. Similarly, + verify_true (R) works by packaging a _Static_assert inside a struct + that is an operand of sizeof. + + The code below uses several ideas for C++ compilers, and for C + compilers that do not support _Static_assert: * The first step is ((R) ? 1 : -1). Given an expression R, of integral or boolean or floating-point type, this yields an @@ -109,15 +125,9 @@ __COUNTER__ macro that can let us generate unique identifiers for each dummy function, to suppress this warning. - * This implementation exploits the fact that GCC does not warn about - the last declaration mentioned above. If a future version of GCC - introduces a warning for this, the problem could be worked around - by using code specialized to GCC, just as __COUNTER__ is already - being used if available. - - #if 4 <= __GNUC__ - # define verify(R) [another version to keep GCC happy] - #endif + * This implementation exploits the fact that older versions of GCC, + which do not support _Static_assert, also do not warn about the + last declaration mentioned above. * In C++, any struct definition inside sizeof is invalid. Use a template type to work around the problem. */ @@ -148,6 +158,13 @@ template struct verify_type__ { unsigned int verify_error_if_negative_size__: w; }; # define verify_true(R) \ (!!sizeof (verify_type__<(R) ? 1 : -1>)) +# elif HAVE__STATIC_ASSERT +# define verify_true(R) \ + (!!sizeof \ + (struct { \ + _Static_assert (R, "verify_true (" #R ")"); \ + int verify_dummy__; \ + })) # else # define verify_true(R) \ (!!sizeof \ @@ -157,7 +174,11 @@ template /* Verify requirement R at compile-time, as a declaration without a trailing ';'. */ -# define verify(R) \ +# if HAVE__STATIC_ASSERT +# define verify(R) _Static_assert (R, "verify (" #R ")") +# else +# define verify(R) \ extern int (* _GL_GENSYM (verify_function) (void)) [verify_true (R)] +# endif #endif -- 2.11.0