Previously we would ignore the effect that an if
statement or ternary's condition exit counter might
have on its branches, as we assumed a condition
can't do any control flow. However, in the case
where the condition throws an error, we need to
account for the error branch.
Ensure that `try?` expressions appropriately
scope the regions generated by child
error-throwing expressions, such that the
non-error branch does not extend beyond the region
of the `try?`.
Previously the branches of a ternary would cut off
the coverage after a throwing expression, since
they have their own region, and we pop child
regions when leaving. Update the logic to use the
existing counter adjustment logic when we leave
the scope, ensuring that we push a new counter to
reflect the exit count of the scope.
The logic here previously worked by computing the
exit count by taking the parent count and
subtracting any control flow that jumped out of the
clauses. With `try` handling fixed, this no longer
works correctly, since a `try` shouldn't be
subtracted if the error is caught be one of the
catches, as that's not actually leaving the
statement. We could write the logic to determine
where a `try` is jumping to, but the logic here is
already pretty brittle, relying on being sprinkled
in various different places.
For now, let's take the more straightforward
approach and handle do-catches the same way we
handle switches, we initialize the exit counter to
0, and add on each exit count of each branch. This
lets us re-use the existing CaseStmt handling
logic. This doesn't necessarily produce the most
optimal counter expressions, but I want to replace
this all with a SILOptimizer pass anyway, which
will be able to much more easily compute optimal
counter expressions.
rdar://100470244