C_ASSERT portability fixes and simplification [PATCH 2/2]

Gerald Pfeifer gerald at pfeifer.com
Sun May 10 13:16:10 CDT 2009


After the previous, preparatory patch, this is the one that really
addresses the core of the issue.

GCC 4.5 will fail to build dlls/gdi32/tests/generate.c with dozens of
instances of the following error message:

  generated.c: In function 'test_pack_ABC':
  generated.c:97: error: object with variably modified type must have no linkage
  generated.c:100: error: object with variably modified type must have no linkage

The code in question is TEST_FIELD_OFFSET(ABC, abcA, 0) which expands
to C_ASSERT(FIELD_OFFSET(type, field) == offset).  In include/winnt.h
we then have

  # define C_ASSERT(e) extern char __C_ASSERT__[(e)?1:-1] __attribute__((unused))

which brings us to the actual problem: the C standard, and now GCC 4.5,
do not allow external arrays of non-fixed size.

One way to address this is changing the C_ASSERT macro to

  # define C_ASSERT(e) { char __C_ASSERT__[(e)?1:-1] __attribute__((unused)); }

that is, removing the extern and putting this into a basic block of its
own.

This nicely addresses the problem for dlls/gdi32/tests/generate.c and
similar cases.

Gerald

ChangeLog:
Make C_ASSERT more portable (and standards-conforming).

diff --git a/include/winnt.h b/include/winnt.h
index abcc502..ccbf182 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -292,7 +292,8 @@ extern "C" {
 #if defined(_MSC_VER)
 # define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
 #elif defined(__GNUC__) 
-# define C_ASSERT(e) extern char __C_ASSERT__[(e)?1:-1] __attribute__((unused))
+# define C_ASSERT(e) { char __C_ASSERT__[(e)?1:-1] __attribute__((unused)); }
+/* # define C_ASSERT(e) extern char __C_ASSERT__[(e)?1:-1] __attribute__((unused)) */
 #else
 # define C_ASSERT(e)
 #endif



More information about the wine-patches mailing list