I can explain what SlickEdit really does (and some of why).
#ifdef SOMETHING
path1
#else
path2
#endif
If you have configured "SOMETHING" in the C/C++ preprocessing, then SlickEdit knows about the symbol and that is that, it will chose the appropriate path.
If not then SlickEdit's tagging engine parses both paths. (note that a lot of other features know nothing about the C/C++ preprocessing). This is fine sometimes, when the result is still syntactic, but as in the example chrisant gave with SomeType, you would wind up with mismatched braces. Another typical example, a little less harmful, is with function prototypes.
void myFunction(
int handle,
#if SOMETHING
int x, int y, int z,
int tm
#else
Point p,
int tm
#endif
);
In reality, this function has either 3 or 5 parameters, but SlickEdit's going to think it has 7. That's because SlickEdit is even more powerful than your code. :-) It likes a challenge.
SlickEdit does not look at your project tag file to resolve preprocessing. One reason is performance, another is accuracy. We do not tag "#undef" as a symbol definition (because it, well, isn't), so for one, we wouldn't know when a symbol is explicitely undefined, and we can't know when a symbol is implicitly undefined, unless we do full preprocessing of everything including system header files. The third reason is that sometimes your project defines preprocessor symbols different ways in different header files or preprocessing paths. Again, it this scenario, we would be back to just guessing. Our preference is to not guess rather than to guess wrong.
We are looking into adding a workspace level preprocessing configuration step that will let you pull in #defines from your workspace. This too is tricky, because there are four kinds of #defines: (a) constants, expressions, code snippets (b) code generators / hacky old-style templates (c) targets for #ifndef / #ifdef, and (d) symbols used for any/all of the above. We are only interested in preprocessing away (b) and (c). If we fully preprocessed all symbols, then some of your tagging results become quite boring (lose information).
#define THE_INTERNET_ON_ITS_SIDE 333
int someFunction(int arg1=THE_INTERNET_ON_ITS_SIDE);
would be tagged as
int someFunction(int arg1=333);
#if/#ifdef are just a small part of preprocessing. There is also code-generating macros, and in fact, from a pure parsing perspective, any identifier could be a macro. This is again why, for performance we stick to the C/C++ preprocessing setup and do not query the workspace tag file for every symbol we see. Example:
int f _PROTO(int x, int y, int z);
If we know about _PROTO(), then no problem. If not, this just looks like garbage (in fact, SlickEdit will tag it as a prototype for a function named _PROTO(). This is a pretty common problem, and people wonder why they don't get any tagging for their functions and why the Preview window has such a hard time listing all the definitions of _PROTO(). Defining that one macro for example, in C/C++ preprocessing can completely transform your SlickEdit experience.
But, returning to the automation question, if you have a _PROTO, chances are it's defined something like this.
#ifdef USING_ANSI
#define _PROTO(p) (p);
#else
#define _PROTO(p) ();
#endif
So we only know which version to use if we know what USING_ANSI is, which will ultimately depend on what compiler you are using today.
So, yeah, it's a hard problem.