Here's the simple test case I cooked up :
void fuck() { #ifdef RR_ASSERT #pragma RR_PRAGMA_MESSAGE("yes") #else #pragma RR_PRAGMA_MESSAGE("no") #endif RR_ASSERT(true); }And here is the compiler error :
1>.\rrSurfaceSTBI.cpp(43) : message: yes 1>.\rrSurfaceSTBI.cpp(48) : error C3861: 'RR_ASSERT': identifier not foundEh !? Serious WTF !? I know RR_ASSERT is defined, and then it says it's not found !? WTF !?
Well a few lines above that is the key. There was this :
#undef assert #define assert RR_ASSERTwhich seems like it couldn't possibly cause this, right? It's just aliasing the standard C assert() to mine. Not possible related, right? But when I commented out that bit the problem went away. So of course my first thought is clean-rebuild all, did I have precompiled headers on by mistake? etc. I assume the compiler has gone mad.
Well, it turns out that somewhere way back in RR_ASSERT I was in a branch that caused me to have this definition for RR_ASSERT :
#define RR_ASSERT(exp) assert(exp)This creates a strange state for the preprocessor. RR_ASSERT is now a recursive macro. When you actually try to use it in code, the preprocessor apparently just bails and doesn't do any text substitution. But, the name of the preprocessor symbol is still defined, so my ifdef check still saw RR_ASSERT existing. Evil.
BTW the thing that kicked this off is that fucking VC x64 doesn't support inline assembly. ARGH YOU COCK ASS. Because of that we had long ago written something like
#ifdef _X86 #define RR_ASSERT_BREAK() __asm int 3 #else #define RR_ASSERT_BREAK() assert(0) #endifwhich is what caused the difficulty.
8 comments:
btw, you can also use the __debugbreak intrinsic.
Except for the fact that we're sharing the code and I develop in VC6.
Well, you can just use __debugbreak for the x64 builds.
VC x64 not supporting inline ASM bit me in a major way recently: I really did need to write some ASM code to interface with code generated for a different calling convention, plus some small SSE tidbits that needed a certain register mapping. Not only is it inconvenient, it also forces me to make some things that are pure implementation helpers for one file public symbols, and in this case it also made me use fucking MASM. I promptly got reminded why I avoided that POS for years when it randomly decided to assemble "cmpneqps xmm8, [rdx + blah]" as "cmpeqps xmm8, [rdx + blah]" in some places. What the hell, people?
"btw, you can also use the __debugbreak intrinsic. "
Yeah, once I figured out that the problem was a circular define, the solution was easy.
"VC x64 not supporting inline ASM bit me in a major way recently:"
Yeah that's very annoying.
There's a DebugBreak() function in windows.h, you can use that on all platforms and it works with VC6 too.
To be more precise, preprocessor substitutes RR_ASSERT(expr) by assert(expr), and then substituted assert by RR_ASSERT. Which is sometimes a useful behavior, i.e.
#define new new(__FILE__, __LINE__)
does a single substitution (yes, I know that this does not work with placement new and that there are better methods).
"To be more precise, preprocessor substitutes RR_ASSERT(expr) by assert(expr), and then substituted assert by RR_ASSERT. Which is sometimes a useful behavior, i.e."
Oh yeah, you are quite right.
http://xkcd.com/754/
Post a Comment