verify.h

Go to the documentation of this file.
00001 /* Compile-time assert-like macros.
00002 
00003    Copyright (C) 2005, 2006 Free Software Foundation, Inc.
00004 
00005    This program is free software: you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published by
00007    the Free Software Foundation; either version 3 of the License, or
00008    (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00017 
00018 /* Written by Paul Eggert, Bruno Haible, and Jim Meyering.  */
00019 
00020 #ifndef VERIFY_H
00021 # define VERIFY_H 1
00022 
00023 /* Each of these macros verifies that its argument R is nonzero.  To
00024    be portable, R should be an integer constant expression.  Unlike
00025    assert (R), there is no run-time overhead.
00026 
00027    There are two macros, since no single macro can be used in all
00028    contexts in C.  verify_true (R) is for scalar contexts, including
00029    integer constant expression contexts.  verify (R) is for declaration
00030    contexts, e.g., the top level.
00031 
00032    Symbols ending in "__" are private to this header.
00033 
00034    The code below uses several ideas.
00035 
00036    * The first step is ((R) ? 1 : -1).  Given an expression R, of
00037      integral or boolean or floating-point type, this yields an
00038      expression of integral type, whose value is later verified to be
00039      constant and nonnegative.
00040 
00041    * Next this expression W is wrapped in a type
00042      struct verify_type__ { unsigned int verify_error_if_negative_size__: W; }.
00043      If W is negative, this yields a compile-time error.  No compiler can
00044      deal with a bit-field of negative size.
00045 
00046      One might think that an array size check would have the same
00047      effect, that is, that the type struct { unsigned int dummy[W]; }
00048      would work as well.  However, inside a function, some compilers
00049      (such as C++ compilers and GNU C) allow local parameters and
00050      variables inside array size expressions.  With these compilers,
00051      an array size check would not properly diagnose this misuse of
00052      the verify macro:
00053 
00054        void function (int n) { verify (n < 0); }
00055 
00056    * For the verify macro, the struct verify_type__ will need to
00057      somehow be embedded into a declaration.  To be portable, this
00058      declaration must declare an object, a constant, a function, or a
00059      typedef name.  If the declared entity uses the type directly,
00060      such as in
00061 
00062        struct dummy {...};
00063        typedef struct {...} dummy;
00064        extern struct {...} *dummy;
00065        extern void dummy (struct {...} *);
00066        extern struct {...} *dummy (void);
00067 
00068      two uses of the verify macro would yield colliding declarations
00069      if the entity names are not disambiguated.  A workaround is to
00070      attach the current line number to the entity name:
00071 
00072        #define GL_CONCAT0(x, y) x##y
00073        #define GL_CONCAT(x, y) GL_CONCAT0 (x, y)
00074        extern struct {...} * GL_CONCAT(dummy,__LINE__);
00075 
00076      But this has the problem that two invocations of verify from
00077      within the same macro would collide, since the __LINE__ value
00078      would be the same for both invocations.
00079 
00080      A solution is to use the sizeof operator.  It yields a number,
00081      getting rid of the identity of the type.  Declarations like
00082 
00083        extern int dummy [sizeof (struct {...})];
00084        extern void dummy (int [sizeof (struct {...})]);
00085        extern int (*dummy (void)) [sizeof (struct {...})];
00086 
00087      can be repeated.
00088 
00089    * Should the implementation use a named struct or an unnamed struct?
00090      Which of the following alternatives can be used?
00091 
00092        extern int dummy [sizeof (struct {...})];
00093        extern int dummy [sizeof (struct verify_type__ {...})];
00094        extern void dummy (int [sizeof (struct {...})]);
00095        extern void dummy (int [sizeof (struct verify_type__ {...})]);
00096        extern int (*dummy (void)) [sizeof (struct {...})];
00097        extern int (*dummy (void)) [sizeof (struct verify_type__ {...})];
00098 
00099      In the second and sixth case, the struct type is exported to the
00100      outer scope; two such declarations therefore collide.  GCC warns
00101      about the first, third, and fourth cases.  So the only remaining
00102      possibility is the fifth case:
00103 
00104        extern int (*dummy (void)) [sizeof (struct {...})];
00105 
00106    * This implementation exploits the fact that GCC does not warn about
00107      the last declaration mentioned above.  If a future version of GCC
00108      introduces a warning for this, the problem could be worked around
00109      by using code specialized to GCC, e.g.,:
00110 
00111        #if 4 <= __GNUC__
00112        # define verify(R) \
00113            extern int (* verify_function__ (void)) \
00114                       [__builtin_constant_p (R) && (R) ? 1 : -1]
00115        #endif
00116 
00117    * In C++, any struct definition inside sizeof is invalid.
00118      Use a template type to work around the problem.  */
00119 
00120 
00121 /* Verify requirement R at compile-time, as an integer constant expression.
00122    Return 1.  */
00123 
00124 # ifdef __cplusplus
00125 template <int w>
00126   struct verify_type__ { unsigned int verify_error_if_negative_size__: w; };
00127 #  define verify_true(R) \
00128      (!!sizeof (verify_type__<(R) ? 1 : -1>))
00129 # else
00130 #  define verify_true(R) \
00131      (!!sizeof \
00132       (struct { unsigned int verify_error_if_negative_size__: (R) ? 1 : -1; }))
00133 # endif
00134 
00135 /* Verify requirement R at compile-time, as a declaration without a
00136    trailing ';'.  */
00137 
00138 # define verify(R) extern int (* verify_function__ (void)) [verify_true (R)]
00139 
00140 #endif

Generated on Tue Oct 21 18:28:19 2008 for gsasl by  doxygen 1.5.6