There's no ambiguity; let's look up the actual grammar (C++11 §A.5):
The while and for are under iteration-statement
iteration-statement:
while (condition) statement
do
statement while ( expression)
for ( for-init-statement conditionopt;
expressionopt) statement
(each row is an alternative pattern that satisfies the term that precedes the colon in the first row; words in italic are references to other grammar rules; the opt marks optional terms)
if and if/else are under selection-statement:
selection-statement:
if ( condition ) statement
if ( condition )
statement else statement
switch ( condition ) statement
Now, as you can see they all require one, single, generic "statement" to execute, with no explicit mention of the braces; statement, in turn, is defined as:
statement:
labeled-statement
attribute-specifier-seqopt
expression-statement
attribute-specifier-seqopt
compound-statement
attribute-specifier-seqopt
selection-statement
attribute-specifier-seqopt
iteration-statement
attribute-specifier-seqopt
jump-statement
declaration-statement attribute-specifier-seqopt
try-block
let's forget about attribute-specifier-seqopt; the point to take home is that a statement in turn can be any of the while/for/if above, plus some other stuff, including the compound-statement, i.e. the braces:
compound-statement:
{ statement-seqopt }
statement-seq:
statement
statement-seq statement
(which is a formal way to say that inside the braces you can put one or more statements)
Now, with this knowledge we can disentangle your example by thinking mechanically like the parser does:
for (condition)
if (condition)
doA();
else
doB();
if (condition)
doC();
else
doD();
the for after the stuff in the () wants a statement; let's try to parse what follows as such:
there's an if; if either wants just a statement of a statement followed by else and another statement; let's see:
doA() is an expression-statement
- an
else follows
doB() is an expression-statement
thus the whole if (condition) doA(); else doB(); is a statement, in particular a selection-statement
ok, we have full statement to provide as loop body to the for, so the for statement is completed;
then, we have an if-else, which is parsed as above
doC() is an expression-statement
- an
else follows
doD() is an expression-statement
Thus, the final "braced" interpretation is
for (condition) {
if (condition) {
doA();
} else {
doB();
}
}
if (condition) {
doC();
} else {
doD();
}