Sema: Ban forward references of captured values from 'defer' body

While 'defer' is implemented as a local function, it doesn't
behave as one. In particular, since SILGen runs it after
destroying all local bindings that appear after the 'defer'
definition, the body of a 'defer' cannot forward reference
captured bindings the way that local functions can.

Note that I had to remove a SILGen test case for an older,
related issue. The new diagnostic in Sema catches these cases
earlier.

Fixes rdar://problem/75088379.
This commit is contained in:
Slava Pestov
2021-03-15 16:29:03 -04:00
parent 4c7f0fd43b
commit b6381d4549
6 changed files with 69 additions and 51 deletions

View File

@@ -245,22 +245,16 @@ void SILGenFunction::emitCaptures(SILLocation loc,
auto &Diags = getASTContext().Diags;
SourceLoc loc;
bool isDeferBody;
if (closure.kind == SILDeclRef::Kind::DefaultArgGenerator) {
auto *param = getParameterAt(closure.getDecl(),
closure.defaultArgIndex);
loc = param->getLoc();
isDeferBody = false;
} else {
auto f = *closure.getAnyFunctionRef();
loc = f.getLoc();
isDeferBody = f.isDeferBody();
}
Diags.diagnose(loc,
isDeferBody
? diag::capture_before_declaration_defer
: diag::capture_before_declaration,
Diags.diagnose(loc, diag::capture_before_declaration,
vd->getBaseIdentifier());
Diags.diagnose(vd->getLoc(), diag::captured_value_declared_here);
Diags.diagnose(capture.getLoc(), diag::value_captured_here);