http://bugs.winehq.org/show_bug.cgi?id=25945
Summary: C_ASSERT doesn't fail if given non-constant expression Product: Wine Version: 1.1.22 Platform: x86 OS/Version: Linux Status: UNCONFIRMED Severity: minor Priority: P2 Component: -unknown AssignedTo: wine-bugs@winehq.org ReportedBy: alexander.scott.johns+winebug@googlemail.com
In commit wine-1.1.21-63-g5d31eb9 AJ changed the definition of C_ASSERT (in include/winnt.h) to make it compatible with newer versions of GCC.
Roughly, the change was:
-#define C_ASSERT(e) extern char __C_ASSERT__[(e)?1:-1] __attribute__((unused)) +#define C_ASSERT(e) extern void __C_ASSERT__(int [(e)?1:-1])
Unfortunately, in GCC 4.4.3, the new definition of C_ASSERT doesn't fail when given a non-constant expression. E.g.:
C_ASSERT(rand() == -1); /* ignored */
I think this is because GCC (as per C99) is treating the parameter of __C_ASSERT__ as a VLA (variable length array), and so its type is equivalent to int[*].
http://bugs.winehq.org/show_bug.cgi?id=25945
Alexander Scott-Johns alexander.scott.johns+winebug@googlemail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download, source CC| |julliard@codeweavers.com
--- Comment #1 from Alexander Scott-Johns alexander.scott.johns+winebug@googlemail.com 2011-01-31 19:07:50 CST --- We could try something like (based on linux/kernel.h's BUILD_BUG_*):
#define C_ASSERT(e) (sizeof(struct { signed __static_assert : (e)?1:-1; }))
This will evaluate to sizeof(int), and can be used in constant expressions. I'm not sure if this version of C_ASSERT can be made into a declaration, as using it inside a function prototype makes GCC complain: "anonymous struct declared inside parameter list".
If C99 features are available, this should work (it uses array literals and array designators):
#define C_ASSERT(e) \ extern void __C_ASSERT__(int [sizeof((char[]){ [-!(e)] = 0 })])
The _Static_assert(e,m) thing from C1x is implemented in GCC 4.6. If it's available, we should use it, instead of using a homebrew solution (which can then be a hacky, not-accepted-by-modern-GCC thing).
#ifdef _Static_assert /* There is a way to check for this, right? */ # define C_ASSERT(e) _Static_assert((e), #e " was false") #elsif defined(_MSC_VER) # define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] #elsif __STDC_VERSION__ >= 199901L # define C_ASSERT(e) \ extern void __C_ASSERT__(int [sizeof((char[]){ [-!(e)] = 0 })]) #else /* C99 not supported: no VLAs */ # define C_ASSERT(e) extern void __C_ASSERT__(int [(e)?1:-1]) #endif
http://bugs.winehq.org/show_bug.cgi?id=25945
--- Comment #2 from Alexander Scott-Johns alexander.scott.johns+winebug@googlemail.com 2011-02-02 10:34:34 CST --- According to the GCC documentation, GCC 2.95 supports array designators and (rvalue) array literals. And according to the c1x draft, <assert.h> should define a static_assert macro. So this should work:
#if defined(static_assert) # define C_ASSERT(e) static_assert((e), #e " should be true") #elif defined(_MSC_VER) # define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] #else # define C_ASSERT(e) \ extern void __C_ASSERT__(int [sizeof((char[]){ [-!(e)] = 0 })]) #endif
http://bugs.winehq.org/show_bug.cgi?id=25945
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- CC|julliard@codeweavers.com |
http://bugs.winehq.org/show_bug.cgi?id=25945
Jerome Leclanche adys.wh@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |adys.wh@gmail.com
http://bugs.winehq.org/show_bug.cgi?id=25945
André H. nerv@dawncrow.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |nerv@dawncrow.de
--- Comment #3 from André H. nerv@dawncrow.de 2013-07-01 16:06:54 CDT --- code wasn't touched since 2009, still true, though i didn't test
https://bugs.winehq.org/show_bug.cgi?id=25945
IvanDSM snesivan1@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |snesivan1@gmail.com
--- Comment #4 from IvanDSM snesivan1@gmail.com --- The code for C_ASSERT is still the same in Wine 5.0. Is this an actual issue or can we ignore this?