The original fix for PR19864 (r209764) indirectly caused the loop
backedge of a (for \ if \ x) construct to be attributed to the 'if' line
(rather than the 'x' line where it was previously). It did this by
changing the location of the cleanup for the 'if'.
This was confusing all around - it's not the job of the 'if' to decide
where a loop backedge is located, source-wise, it was just happening by
accident because no other location was being set*. Instead, if we
specifically set the location before the backedge is emitted, its
location is now independent of that of the if's cleanup (this change was
made in r215766). So now you don't get strange nexting behavior in your
debugger where you could go "for -> if -> x -> /if/ -> for" as the
backedge was attributed to the 'if' line. Now the backedge is attributed
to the 'for' so it looks more natural (for -> if -> x -> for -> if ->
... ).
That is, unless the 'if' has cleanup (dtors) to run. In which case those
lines are attributed to the 'x' line and, in some circumstances, the
debugger may 'next' to them.
It looks as though GCC (though I don't know about LLDB) will avoid
nexting onto the dtor line somehow (I'm guessing some kind of
heuristic, but I haven't experimented too carefully to see just how/when
it works) so, even though the dtor is attributed to the 'x' line, and if
you break in the dtor and 'next' up you reach the 'x' line, if you next
from the 'if' and the condition is false, you'll end up at the 'for'
line and the dtor will have already been executed.
This breaks down when both the natural dtor /and/ exception handling
cleanup are required. GCC's output places the EH cleanup code after the
non-exceptional dtor invocation codepath. Clang places the EH cleanup
code before the non-exceptional dtor. This difference seems to cause GDB
to not skip the dtor line when 'next'ing with Clang's debug info, which
is unfortunate. I'm not sure if it's better fixed in GDB or Clang.
In brief:
Given "for / if / x"
Without any dtors in the 'if' scope, no behavior change.
With dtors:
Previous behavior (if true): for -> if -> x -> if -> for -> ...
(if false): for -> if -> if -> for -> if -> if
New behavior (under GDB):
Without EH cleanup (if true): for -> if -> x -> for -> ...
(if false): for -> if -> for -> ...
With EH cleanup (eg: if x can throw), even if false:
for -> if -> x -> for -> ...