[ownership-verifier] Teach the ownership verifier how to handle unreachable code.

There are a few different use cases here:

1. In Raw SIL, no return folding may not have been run yet implying that a call
to a no-return function /can/ have arbitrary control flow after it (consider
mandatory inlined functions). We need to recognize that the region of code that
is strictly post dominated by the no-return function is "transitively
unreachable" and thus leaking is ok from that point. *Footnote 1*.

2. In Canonical and Raw SIL, we must recognize that unreachables and no-return
functions constitute places where we are allowed to leak.

rdar://29791263

----

*Footnote 1*: The reason why this is done is since we want to emit unreachable
code diagnostics when we run no-return folding. By leaving in the relevant code,
we have preserved all of the SILLocations on that code allowing us to create
really nice diagnostics.
This commit is contained in:
Michael Gottesman
2017-01-29 15:27:32 -08:00
parent c309a286a3
commit ed67bf9f21
7 changed files with 305 additions and 29 deletions

View File

@@ -305,3 +305,22 @@ SILBasicBlock::getFunctionArguments() const {
};
return makeTransformArrayRef(getArguments(), F);
}
/// Returns true if this block ends in an unreachable or an apply of a
/// no-return apply or builtin.
bool SILBasicBlock::isNoReturn() const {
if (isa<UnreachableInst>(getTerminator()))
return true;
auto Iter = prev_or_begin(getTerminator()->getIterator(), begin());
FullApplySite FAS = FullApplySite::isa(const_cast<SILInstruction *>(&*Iter));
if (FAS && FAS.isCalleeNoReturn()) {
return true;
}
if (auto *BI = dyn_cast<BuiltinInst>(&*Iter)) {
return BI->getModule().isNoReturnBuiltinOrIntrinsic(BI->getName());
}
return false;
}