I previously called these braceless scopes, and ended up writing more in discussion with Jens that I did on my blog - but now I come to needed it, and further back in time than I expected I find this gem carbuncle below.
(By attachable-scope I mean a braced-scope that get's attached to the expansion of previous macro, perhaps as the body of a function definition, or a for loop, or even an else clause).
Hah! Your example there was the clue to propagating breaks.
Thanks to your tip on the gcc equivalence using BREAKOUT and BREAKIN I can contrive a bunch of macros that expand to this:
123456789main() {
int a;
for (a=1; a<=2; a++) {
printf("Main context a=%d\n", a);
if (0) { break_line_6: break ; } else for (int o = 0; o >=0; ) if (o == 1) { printf("Detected break\n"); goto break_line_6; } else
for (int i=0; !o && (o=1), i==0; o=-1, i=-1 ) { printf("Inner context\n"); break; }
}
}
it does not require gcc-isms – sadly the C style is lacking but it functions as desired
123456789101112131415161718#define GENSYM_CONCAT(name, salt) name ## salt
#define GENSYM2(name, salt) GENSYM_CONCAT(name, salt)
#define GENSYM(name) GENSYM2(name, __LINE__)
#define _BRACELESS_SCOPE(__label__, _declaration_) \
if (0) { __label__: break ; } else for (int _o = 0; _o >=0; ) if (_o == 1) goto __label__; else \
for (_declaration_; !_o && (_o=1); _o=-1) \
#define BRACELESS_SCOPE(_declaration_) _BRACELESS_SCOPE(GENSYM(break_line_) , _declaration_)
main() {
int a;
for (a=1; a<=2; a++) {
printf("Main context a=%d\n", a);
BRACELESS_SCOPE(char* message="hello") { printf("Inner context: %s\n", message); break; }
}
}
The main deficiency is that a single macro cannot cannot ultimately expand to more than one of these constructs, nor can it be used twice on the same line, or the generated labels will conflict. __COUNTER__ where supported could be passed instead of __LINE__. I guess this is something you already addressed in P99 if I look again…
It's just what I needed as I convert a narrating block logger (that annotates progress through a block scope) from gcc-isms to clang-isms.
It originally expanded to a nested function forward definition, a setup block, a nested function invocation, a clean-up block, followed by a the first half of a nested function definition which sticks onto a following scope that becomes the body.
clang won't take nested functions (even without arguments) and clang's objective-C style blocks is no help as it can't access the variables in the calling scope as gcc does.
Knowing that I've passed this way before I look at this and this, before finally recovering the carbuncle above which is to be pressed into service.