T O P I C R E V I E W |
Hexagonal |
Posted - Feb 15 2012 : 07:26:06 AM Hi all.
By lucky chance, I found another big cause of Visual Assist troubles. When a macro name gets redefined, VA always substitutes the first definition:
#define TMP_MACRO(funcName) \ bool funcName(int value);
TMP_MACRO(canNeg)
TMP_MACRO(canAbs)
#undef TMP_MACRO
////
#define TMP_MACRO(funcName) \ bool funcName(int A, int B);
TMP_MACRO(canAdd)
TMP_MACRO(canSub)
#undef TMP_MACRO
////
void main()
{
canNeg(0); // OK
canAdd(); // <== Takes one parameter?
}
In real projects, the wrong substitution results in many symbols being unobserved by VA.
Temporary macro is very widely used technique, for example look at BOOST_TMP_MACRO usage.
|
8 L A T E S T R E P L I E S (Newest First) |
Hexagonal |
Posted - Feb 22 2012 : 12:51:17 AM Thank you!
A preprocessor with C scope support is a dream of me too. At least, with some "namespaces".
|
feline |
Posted - Feb 22 2012 : 12:02:57 AM I had hoped that this could be tied to a standard C scope, but there is no reason why it should. The magic of the pre-processor. I have put in a feature request for this, but it is not going to be a quick or easy fix:
case=64840 |
Hexagonal |
Posted - Feb 21 2012 : 09:31:03 AM Hi Feline.
Of course, preprocessor macro is not tied to any C++ scope, because it's preprocessor. The preprocessor doesn't know about the underlying language, for example, it can be used as well for preprocessing ASM files.
Its scope is defined by preprocessing directives: #define <-- Scope begins #undef <-- Scope ends
So my proposal is to support #undef and following #define directives. #undef is basic functionality, because, as you mentioned, the lesser macro scope, the better.
|
feline |
Posted - Feb 20 2012 : 7:14:48 PM Are your temporary macros used a file scope, or are they mainly used inside a function, or other item that would limit their scope?
Calling them "temporary" unfortunately does not stop them being used for used for hundreds, if not thousands of lines of code. Also such a macro can wrap a #include statement, even if it is only used briefly.
The main clue here is that they are undefined at some point, so we would need to look for that. It is the scoping though that concerns me, I suspect this could be tricky for VA, since its not tied to the normal scoping structures. |
Hexagonal |
Posted - Feb 17 2012 : 01:17:39 AM Hi Feline.
You never look up for this macro. It's temporary macro. And it's never defined, so you never need to trace up for the last definition.
It's temporary: you define it, it makes something, then you undefine it.
Here is very simple example:
#include <math.h>
#define TMP_MACRO(Type, baseFunc) \ inline Type myAbs(Type value) \ {return baseFunc(value);}
TMP_MACRO(int, abs)
TMP_MACRO(long, labs)
TMP_MACRO(float, fabsf)
TMP_MACRO(double, fabs)
#undef TMP_MACRO
//
// <=== No TMP_MACRO exists here, nobody can use it.
//
P.S. This pattern is not uncommon in real projects, it's not just my crazy idea (one example is Boost, I can find more examples if required). |
feline |
Posted - Feb 16 2012 : 11:20:43 AM Does this not result in very hard to read and understand code? When you find a macro being used, you never know what the macro does, you have to work back up the file for the last time it was redefined. Thinking about this, it sounds like it could become a major problem.
Or am I missing something obvious here? |
Hexagonal |
Posted - Feb 16 2012 : 04:14:40 AM Hi Feline.
But the problem is not about selecting the correct version of a macro.
The problem is:
- Temporary macro is defined.
- Temporary macro is called, defining C++ entities (functions, constants, etc).
- Temporary macro is undefined.
- Repeat 100 times.
In real projects, there are hundreds of such calls, and even if VA selects single macro ideally, 99% of the macro work is lost.
I mean it's not about working with the macro itself, like: finding where is TMP_MACRO, looking for its signature, no.
It's about the macro effect on C code.
Look, now the developer has to give the temporary macro unique name each time, just because VA doesn't support #undef/redefinition:
#define TMP_MACRO_9EC0FEF1(funcName) \ bool funcName(int value);
TMP_MACRO_9EC0FEF1(canNeg)
TMP_MACRO_9EC0FEF1(canAbs)
#undef TMP_MACRO_9EC0FEF1
|
feline |
Posted - Feb 15 2012 : 6:27:26 PM Unfortunately this is somewhere between by design, and a known limitation.
Another place where the same problem comes up is code like:
#if _DEBUG
#define TMP_MACRO(funcName) \ bool funcName(int value);
#else
#define TMP_MACRO(funcName) \ bool funcName(int A, int B);
#endif
Without actually compiling the code, and running a full pre-processor some of these problems are rather hard to work around.
There is some good news here though. If you are encountering one of these problems you can try to re-order the macro so that the "correct" version is the first one VA see's. Another option is to place the correct macro definition into VA's StdAfx.h file, as explained in this FAQ entry:
http://docs.wholetomato.com?W302
So that the correct form of the macro is taken from here, before any of your own code is parsed. |
|
|