I just started compiling my C code with VS 2005 (I was using VS 2003) and I ran across a compilation error that I've never seen with any other Microsoft , Intel or GNU (in multiple *nix platforms) compiler. The code calls macros from other macros and more importantly has an assert. When I compiled with -E, I see the following code generated:
{ if ( (int)((( (void)( (!!(0)) || (_wassert(["0", ["d:\\mywork\\cmochk\\cmoplgrp.c", 3562), 0) ), age = 1 ))) != 0 ) need_cluster = 1 ; } ;Note the bolded letter. The '[' is wrong and is an "L" in code that correctly compiles.
I tried creating a simpler example but unfortunately could not reproduce what I saw with my production code. The code that creates this looks like this:
#include <assert.h>
#define
TED_ONE_DIM( dim_expr ) \{ \
(dim_expr); \
}
#define
TED_ONE_DIM_INT( dim_expr ) TED_ONE_DIM( (dim_expr) )TED_ONE_DIM_INT( ( assert(0), age = 1 ) ) ;
Any ideas about why this is happening
Thanks,
Ted

VS 2005 compile problem with asserts
mz1derful
First of all pasting tokens that do not result in a single pp-token is undefined behavior. So pasting L "foo" yields L"foo" (one token), while
["foo" is not a single pp-token. So the compiler need not do what you'd expect (um, yes, I can already hear some of you saying "it never does").
I believe, there two things in your case. First, arguments passed to a macro invocation are expanded before the macro is executed. Secondly, arguments are expanded except when they are subject to the stringizing (#) or token pasting (##) operators.
But then, I'm not a preprocessor expert. I only keep hearing from the folks on the Boost mailing lists, who know infinitely more than me, that VC's preprocessor is not particulary good at implementing the phases of translation.
BTW: If you're interested in what the preprocessor can do for you take a look at the Boost.Preprocessor library or at Chaos or at the other one whose name I forgot.
-hg
Sean Patzer
That was it - I got what I was asking for but I had to search the code base to see that I was asking for it:)
Here's something that's still confusing to me. I've include a code sample that reproduces the issue below. The first macro compiles correctly but the second fails. Both output the wassert( L"... ) so why doesn't the first fail
Thanks,
Ted
#include
<assert.h>#define
L [#define
TED_ONE_DIM( dim_expr ) \{ \
(dim_expr); \
}
#define
TED_ONE_DIM_INT( dim_expr ) TED_ONE_DIM( (dim_expr) )int
main( int argc, char *argv[] ){
TED_ONE_DIM( ( assert(0) ) ) ;
TED_ONE_DIM_INT( ( assert(0) ) ) ;
return
0 ;}
Compiling with /E shows:
------ Build started: Project: Test_macro, Configuration: Debug Win32 ------
Compiling...
test.c
int main( int argc, char *argv[] )
{
{ (( (void)( (!!(0)) || (_wassert(L"0", L"d:\\mywork\\vs2005\\test_macro\\test.c", 16), 0) ) )); } ;
{ ((( (void)( (!!(0)) || (_wassert(["0", ["d:\\mywork\\vs2005\\test_macro\\test.c", 17), 0) ) ))); } ;
return 0 ;
}
Sinc at devBiz
No idea, what's causing your specific issue. Maybe a
#define L [
somewhere (in which case, I'd say you got what you deserve :-O). Anyhow you can try to get the macro definitions at a particular point. By injecting some code like:
"foo(x)" = foo(x)
at the macro expansion site and taking a look at the preprocessed output. You'll probably want
"_CRT_WIDE(x)" = _CRT_WIDE(x)
"__CRT_WIDE(x)" = __CRT_WIDE(x)
"L" = L
where your assert is expanded.
-hg