Jim Meyering wrote: > The point of using a bitfield width was to ensure that improper > usage (non-constant argument) like this provokes an error even with > non-gcc compilers: > > void foo (int n) { verify (n); } > > With the preceding, array-dimension-based approach, > the erroneous usage would be accepted once again.
Ah, I see. That wasn't clear from the comments. > to verify.c version 1.6 in coreutils' CVS. > > <http://savannah.gnu.org/cgi-bin/viewcvs/coreutils/coreutils/lib/verify.h?rev=1.6&content-type=text/plain> This one also has some interesting trick. > Just don't use verify twice on the same line. That's not a useful restriction. GNU clisp for example uses lots of macros that expand into C compound statements, and often several of them are triggered from the same line of code. If we can get away without this restriction, we should. And we can. See appended patch. I committed a file tests/test-verify.c that you can test it against. Bruno diff -c -3 -r1.1 verify.h *** lib/verify.h 22 Sep 2005 22:56:29 -0000 1.1 --- lib/verify.h 23 Sep 2005 14:02:23 -0000 *************** *** 16,22 **** along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ ! /* Written by Paul Eggert and Jim Meyering. */ #ifndef VERIFY_H # define VERIFY_H 1 --- 16,22 ---- along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ ! /* Written by Paul Eggert, Jim Meyering, Bruno Haible. */ #ifndef VERIFY_H # define VERIFY_H 1 *************** *** 24,31 **** # define GL_CONCAT0(x, y) x##y # define GL_CONCAT(x, y) GL_CONCAT0 (x, y) ! /* A type that is valid if and only if R is nonzero. ! R should be an integer constant expression. verify_type__ and verify_error_if_negative_size__ are symbols that are private to this header file. */ --- 24,33 ---- # define GL_CONCAT0(x, y) x##y # define GL_CONCAT(x, y) GL_CONCAT0 (x, y) ! /* A type that is valid if and only if R is a constant expression with nonzero ! value. ! R should be a boolean or integer expression. ! Verify that R is a constant expression and that R evaluates to true. verify_type__ and verify_error_if_negative_size__ are symbols that are private to this header file. */ *************** *** 34,57 **** /* Verify requirement R at compile-time, as a declaration. R should be an integer constant expression. ! Unlike assert, there is no run-time overhead. ! The implementation uses __LINE__ to lessen the probability of ! generating a warning that verify_function_NNN is multiply declared. ! However, even if two declarations in different files have the same ! __LINE__, the multiple declarations are still valid C89 and C99 ! code because they simply redeclare the same external function, so ! no conforming compiler will reject them outright. */ ! ! # define verify(R) \ ! extern verify_type__ (R) GL_CONCAT (verify_function_, __LINE__) (void) /* Verify requirement R at compile-time, as an expression. ! R should be an integer constant expression. Unlike assert, there is no run-time overhead. This macro can be used in some contexts where verify cannot, and vice versa. Return void. */ ! # define verify_expr(R) ((void) ((verify_type__ (R) *) 0)) #endif --- 36,70 ---- /* Verify requirement R at compile-time, as a declaration. R should be an integer constant expression. ! Unlike assert, there is no run-time overhead. */ ! # if !HAVE_VARIABLE_SIZE_ARRAYS ! /* This variant is fully portable to all compilers that reject variable- ! size array types. Using __LINE__ is optional; it only serves to ! get prettier error messages after the first error with Solaris cc. */ ! # define verify(R) \ ! extern int (* GL_CONCAT (verify_function_, __LINE__) (void)) \ ! [(R) ? 1 : -1] ! # elif __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 90) ! /* This variant is specific to GNU C and avoids a gcc warning ! "anonymous struct declared inside parameter list". */ ! # define verify(R) \ ! extern int (* verify_function__ (void)) \ ! [__builtin_constant_p ((R)) ? ((R) ? 1 : -1) : -1] ! # else ! /* This variant is fully portable but may generate warnings. */ ! # define verify(R) \ ! extern void verify_function__ (int [sizeof (verify_type__ (R))]) ! # endif /* Verify requirement R at compile-time, as an expression. ! R should be an boolean or integer expression. ! Verify that R is a constant expression and that R evaluates to true. Unlike assert, there is no run-time overhead. This macro can be used in some contexts where verify cannot, and vice versa. Return void. */ ! # define verify_expr(R) \ ! ((void) (verify_type__ (R) *) 0) #endif Index: modules/verify =================================================================== RCS file: /cvsroot/gnulib/gnulib/modules/verify,v retrieving revision 1.1 diff -c -3 -r1.1 verify *** modules/verify 22 Sep 2005 22:56:28 -0000 1.1 --- modules/verify 23 Sep 2005 14:02:23 -0000 *************** *** 3,12 **** --- 3,14 ---- Files: lib/verify.h + m4/verify.m4 Depends-on: configure.ac: + gl_VERIFY Makefile.am: lib_SOURCES += verify.h *** /dev/null 1970-01-01 01:00:00.000000000 +0100 --- m4/verify.m4 2005-09-23 15:47:28.000000000 +0200 *************** *** 0 **** --- 1,16 ---- + # verify.m4 serial 1 + dnl Copyright (C) 2005 Free Software Foundation, Inc. + dnl This file is free software; the Free Software Foundation + dnl gives unlimited permission to copy and/or distribute it, + dnl with or without modifications, as long as this notice is preserved. + + AC_DEFUN([gl_VERIFY], + [ + AC_TRY_COMPILE([], [ + int function (int n) + { + extern void foo (int (*) [n]); + }], + [AC_DEFINE([HAVE_VARIABLE_SIZE_ARRAYS], 1, + [Define to 1 if the compiler supports variable-size arrays.])]) + ]) _______________________________________________ bug-gnulib mailing list bug-gnulib@gnu.org http://lists.gnu.org/mailman/listinfo/bug-gnulib