Skip to content

Commit cef3139

Browse files
committed
[Exclusivity] Treat warning violations with reabstraction thunks as errors
In Swift 4.1 we fixed a false negative and started looking through reabstraction thunks to statically find exclusivity violations. To lessen source impact, we treated these violations as warnings. This commit upgrades those warnings to errors. rdar://problem/34669400
1 parent 302d827 commit cef3139

File tree

5 files changed

+46
-24
lines changed

5 files changed

+46
-24
lines changed

lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -960,25 +960,13 @@ static void checkForViolationsInNoEscapeClosureArguments(
960960
if (!Callee || Callee->empty())
961961
continue;
962962

963-
// For source compatibility reasons, treat conflicts found by
964-
// looking through reabstraction thunks as warnings. A future compiler
965-
// will upgrade these to errors;
966-
DiagnoseAsWarning |= result.isReabstructionThunk;
967-
968-
// For source compatibility reasons, treat conflicts found by
969-
// looking through noescape blocks as warnings. A future compiler
970-
// will upgrade these to errors.
971-
DiagnoseAsWarning |=
972-
(getSILFunctionTypeForValue(Argument)->getRepresentation()
973-
== SILFunctionTypeRepresentation::Block);
974-
975963
// Check the closure's captures, which are a suffix of the closure's
976964
// parameters.
977965
unsigned StartIndex =
978966
Callee->getArguments().size() - result.PAI->getNumArguments();
979967
checkForViolationWithCall(Accesses, Callee, StartIndex,
980968
result.PAI->getArguments(), ASA,
981-
DiagnoseAsWarning, ConflictingAccesses);
969+
/*DiagnoseAsWarning=*/false, ConflictingAccesses);
982970
}
983971
}
984972

test/SILOptimizer/access_enforcement_noescape.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,7 @@ func readBlockWriteInout() {
536536
var x = 3
537537
// Around the call: [modify] [static]
538538
// Inside closure: [read] [static]
539-
// expected-warning@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
539+
// expected-error@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
540540
// expected-note@+1{{conflicting access is here}}
541541
doBlockInout({ _ = x }, &x)
542542
}
@@ -561,7 +561,7 @@ func readBlockWriteInout() {
561561
func noEscapeBlock() {
562562
var x = 3
563563
doOne {
564-
// expected-warning@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
564+
// expected-error@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
565565
// expected-note@+1{{conflicting access is here}}
566566
doBlockInout({ _ = x }, &x)
567567
}

test/SILOptimizer/exclusivity_static_diagnostics.sil

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ bb0(%0 : $Int):
672672
%8 = function_ref @thunkForClosureWithConcreteReturn : $@convention(thin) (Int, @noescape @callee_owned (Int) -> Int) -> @out Int
673673
%9 = partial_apply %8(%7) : $@convention(thin) (Int, @noescape @callee_owned (Int) -> Int) -> @out Int
674674
%10 = convert_escape_to_noescape %9 : $@callee_owned (Int) -> @out Int to $@noescape @callee_owned (Int) -> @out Int
675-
%11 = begin_access [modify] [unknown] %3 : $*Int // expected-warning {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
675+
%11 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
676676
%12 = apply %4<Int>(%11, %10) : $@convention(thin) <T_0> (@inout Int, @noescape @callee_owned (Int) -> @out T_0) -> ()
677677
end_access %11: $*Int
678678
destroy_value %2 : ${ var Int }
@@ -698,7 +698,7 @@ bb0(%0 : $Int):
698698
%10 = function_ref @thunkForCalleeGuaranteed : $@convention(c) (@inout_aliasable @block_storage @noescape @callee_guaranteed () -> ()) -> ()
699699
%11 = init_block_storage_header %7 : $*@block_storage @noescape @callee_guaranteed () -> (), invoke %10 : $@convention(c) (@inout_aliasable @block_storage @noescape @callee_guaranteed () -> ()) -> (), type $@convention(block) @noescape () -> ()
700700
%12 = copy_block %11 : $@convention(block) @noescape () -> ()
701-
%13 = begin_access [modify] [unknown] %3 : $*Int // expected-warning {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
701+
%13 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
702702
%14 = apply %4(%13, %12) : $@convention(thin) (@inout Int, @owned @convention(block) @noescape () -> ()) -> ()
703703
end_access %13 : $*Int
704704
destroy_addr %8 : $*@callee_guaranteed @noescape () -> ()
@@ -725,7 +725,7 @@ bb0(%0 : $Int):
725725
%11 = init_block_storage_header %7 : $*@block_storage @noescape @callee_guaranteed () -> (), invoke %10 : $@convention(c) (@inout_aliasable @block_storage @noescape @callee_guaranteed () -> ()) -> (), type $@convention(block) @noescape () -> ()
726726
%12 = copy_block %11 : $@convention(block) @noescape () -> ()
727727
%13 = enum $Optional<@convention(block) @noescape () -> ()>, #Optional.some!enumelt.1, %12 : $@convention(block) @noescape () -> ()
728-
%14 = begin_access [modify] [unknown] %3 : $*Int // expected-warning {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
728+
%14 = begin_access [modify] [unknown] %3 : $*Int // expected-error {{overlapping accesses, but modification requires exclusive access; consider copying to a local variable}}
729729
%15 = apply %4(%14, %13) : $@convention(thin) (@inout Int, @owned Optional<@convention(block) @noescape () -> ()>) -> ()
730730
end_access %14 : $*Int
731731
destroy_addr %8 : $*@callee_guaranteed @noescape () -> ()

test/SILOptimizer/exclusivity_static_diagnostics.swift

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ struct StructWithTwoStoredProp {
100100
// Take an unsafe pointer to a stored property while accessing another stored property.
101101
func violationWithUnsafePointer(_ s: inout StructWithTwoStoredProp) {
102102
withUnsafePointer(to: &s.f1) { (ptr) in
103-
// expected-warning@-1 {{overlapping accesses to 's.f1', but modification requires exclusive access; consider copying to a local variable}}
103+
// expected-error@-1 {{overlapping accesses to 's.f1', but modification requires exclusive access; consider copying to a local variable}}
104104
_ = s.f1
105105
// expected-note@-1 {{conflicting access is here}}
106106
}
@@ -196,6 +196,18 @@ func callsTakesInoutAndNoEscapeClosure() {
196196
}
197197
}
198198

199+
func inoutReadWriteInout(x: inout Int) {
200+
// expected-error@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
201+
// expected-note@+1{{conflicting access is here}}
202+
takesInoutAndNoEscapeClosure(&x, { _ = x })
203+
}
204+
205+
func inoutWriteWriteInout(x: inout Int) {
206+
// expected-error@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
207+
// expected-note@+1{{conflicting access is here}}
208+
takesInoutAndNoEscapeClosure(&x, { x = 42 })
209+
}
210+
199211
func callsTakesInoutAndNoEscapeClosureWithRead() {
200212
var local = 5
201213
takesInoutAndNoEscapeClosure(&local) { // expected-error {{overlapping accesses to 'local', but modification requires exclusive access; consider copying to a local variable}}
@@ -338,7 +350,7 @@ func testReabstractionThunk(p1: inout ParameterizedStruct<Int>,
338350
// This tests that we still detect access violations for closures passed
339351
// using a reabstraction thunk.
340352
p1.takesFunctionWithGenericReturnType { _ in
341-
// expected-warning@-1 {{overlapping accesses to 'p1', but modification requires exclusive access; consider copying to a local variable}}
353+
// expected-error@-1 {{overlapping accesses to 'p1', but modification requires exclusive access; consider copying to a local variable}}
342354
p2 = p1
343355
// expected-note@-1 {{conflicting access is here}}
344356
return 3
@@ -359,12 +371,21 @@ func takesEscapingBlockClosure
359371
func testCallNoEscapeBlockClosure() {
360372
var i = 7
361373
takesNoEscapeBlockClosure(&i) {
362-
// expected-warning@-1 {{overlapping accesses to 'i', but modification requires exclusive access; consider copying to a local variable}}
374+
// expected-error@-1 {{overlapping accesses to 'i', but modification requires exclusive access; consider copying to a local variable}}
363375
i = 7
364376
// expected-note@-1 {{conflicting access is here}}
365377
}
366378
}
367379

380+
func testCallNoEscapeBlockClosureRead() {
381+
var i = 7
382+
takesNoEscapeBlockClosure(&i) {
383+
// expected-error@-1 {{overlapping accesses to 'i', but modification requires exclusive access; consider copying to a local variable}}
384+
_ = i
385+
// expected-note@-1 {{conflicting access is here}}
386+
}
387+
}
388+
368389
func testCallEscapingBlockClosure() {
369390
var i = 7
370391
takesEscapingBlockClosure(&i) { // no-warning
@@ -388,7 +409,7 @@ func takesInoutAndClosureWithGenericArg<T>(_ p: inout Int, _ c: (T) -> Int) { }
388409
func callsTakesInoutAndClosureWithGenericArg() {
389410
var i = 7
390411
takesInoutAndClosureWithGenericArg(&i) { (p: Int) in
391-
// expected-warning@-1 {{overlapping accesses to 'i', but modification requires exclusive access; consider copying to a local variable}}
412+
// expected-error@-1 {{overlapping accesses to 'i', but modification requires exclusive access; consider copying to a local variable}}
392413
return i + p
393414
// expected-note@-1 {{conflicting access is here}}
394415
}
@@ -399,12 +420,25 @@ func callsTakesInoutAndClosureTakingNonOptionalWithClosureTakingOptional() {
399420
var i = 7
400421
// Test for the thunk converting an (Int?) -> () to an (Int) -> ()
401422
takesInoutAndClosureTakingNonOptional(&i) { (p: Int?) in
402-
// expected-warning@-1 {{overlapping accesses to 'i', but modification requires exclusive access; consider copying to a local variable}}
423+
// expected-error@-1 {{overlapping accesses to 'i', but modification requires exclusive access; consider copying to a local variable}}
403424
i = 8
404425
// expected-note@-1 {{conflicting access is here}}
405426
}
406427
}
407428

429+
// Helper.
430+
func doOne(_ f: () -> ()) {
431+
f()
432+
}
433+
434+
func noEscapeBlock() {
435+
var x = 3
436+
doOne {
437+
// expected-error@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
438+
// expected-note@+1{{conflicting access is here}}
439+
takesInoutAndNoEscapeClosure(&x, { _ = x })
440+
}
441+
}
408442

409443
func inoutSeparateStructStoredProperties() {
410444
var s = StructWithTwoStoredProp()

test/SILOptimizer/exclusivity_static_diagnostics_objc.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class SomeClass {
1212

1313
func testOptionalImport() {
1414
var x = 0
15-
// expected-warning@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
15+
// expected-error@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
1616
// expected-note@+1{{conflicting access is here}}
1717
SomeObjCInterface.perform(&x) { x += 1 }
1818
}

0 commit comments

Comments
 (0)