Skip to content

Commit ae3b13e

Browse files
committed
[Exclusivity] Put suppression for free function swap() behind a flag
And leave suppression off by default for now. We'll use this to evaluate how often swap() causes exclusivity conflicts to be reported.
1 parent 6d35d32 commit ae3b13e

File tree

6 files changed

+52
-29
lines changed

6 files changed

+52
-29
lines changed

include/swift/AST/SILOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ class SILOptions {
143143
/// Emit compile-time diagnostics when the law of exclusivity is violated.
144144
bool EnforceExclusivityStatic = false;
145145

146+
/// Suppress static diagnostics for violations of exclusive access for calls
147+
/// to the Standard Library's swap() free function.
148+
bool SuppressStaticExclusivitySwap = false;
149+
146150
/// Emit checks to trap at run time when the law of exclusivity is violated.
147151
bool EnforceExclusivityDynamic = false;
148152

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ def disable_mandatory_semantic_arc_opts : Flag<["-"], "disable-mandatory-semanti
256256
def assume_parsing_unqualified_ownership_sil : Flag<["-"], "assume-parsing-unqualified-ownership-sil">,
257257
HelpText<"Assume unqualified SIL ownership when parsing SIL">;
258258

259+
def suppress_static_exclusivity_swap : Flag<["-"], "suppress-static-exclusivity-swap">,
260+
HelpText<"Suppress static violations of exclusive access with swap()">;
261+
259262
def enable_sil_opaque_values : Flag<["-"], "enable-sil-opaque-values">,
260263
HelpText<"Enable SIL Opaque Values">;
261264

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,8 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
13241324
|= Args.hasArg(OPT_assume_parsing_unqualified_ownership_sil);
13251325
Opts.EnableMandatorySemanticARCOpts |=
13261326
!Args.hasArg(OPT_disable_mandatory_semantic_arc_opts);
1327+
Opts.SuppressStaticExclusivitySwap |=
1328+
Args.hasArg(OPT_suppress_static_exclusivity_swap);
13271329

13281330
if (Args.hasArg(OPT_debug_on_sil)) {
13291331
// Derive the name of the SIL file for debugging from

lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,8 @@ static void checkStaticExclusivity(SILFunction &Fn, PostOrderFunctionInfo *PO) {
431431
if (auto *AI = dyn_cast<ApplyInst>(&I)) {
432432
// Suppress for the arguments to the Standard Library's swap()
433433
// function until we can recommend a safe alternative.
434-
if (isCallToStandardLibrarySwap(AI, Fn.getASTContext()))
434+
if (Fn.getModule().getOptions().SuppressStaticExclusivitySwap &&
435+
isCallToStandardLibrarySwap(AI, Fn.getASTContext()))
435436
CallsToSuppress.push_back(AI);
436437
}
437438

test/SILOptimizer/exclusivity_static_diagnostics.swift

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,10 @@ func simpleInoutDiagnostic() {
1313
}
1414

1515

16-
func swapSuppression(_ i: Int, _ j: Int) {
16+
func swapNoSuppression(_ i: Int, _ j: Int) {
1717
var a: [Int] = [1, 2, 3]
1818

19-
swap(&a[i], &a[j]) // no-warning
20-
21-
// expected-warning@+2{{modification requires exclusive access}}
22-
// expected-note@+1{{conflicting modification requires exclusive access}}
23-
takesTwoInouts(&a[i], &a[j])
24-
}
25-
26-
func missedSwapSuppression(_ i: Int, _ j: Int) {
27-
var a: [Int] = [1, 2, 3]
28-
29-
// We don't suppress when swap() is used as a value
30-
let mySwap: (inout Int, inout Int) -> () = swap
31-
3219
// expected-warning@+2{{modification requires exclusive access}}
3320
// expected-note@+1{{conflicting modification requires exclusive access}}
34-
mySwap(&a[i], &a[j])
35-
}
36-
37-
func dontSuppressUserSwap(_ i: Int, _ j: Int) {
38-
var a: [Int] = [1, 2, 3]
39-
40-
// Don't suppress on user-defined swap.
41-
func swap<T>(_ p1: inout T, _ p2: inout T) {
42-
return (p1, p2) = (p2, p1)
43-
}
44-
45-
// expected-warning@+2{{modification requires exclusive access}}
46-
// expected-note@+1{{conflicting modification requires exclusive access}}
47-
swap(&a[i], &a[j])
21+
swap(&a[i], &a[j]) // no-warning
4822
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %target-swift-frontend -enforce-exclusivity=checked -suppress-static-exclusivity-swap -emit-sil -primary-file %s -o /dev/null -verify
2+
3+
import Swift
4+
5+
func takesTwoInouts(_ p1: inout Int, _ p2: inout Int) { }
6+
7+
func swapSuppression(_ i: Int, _ j: Int) {
8+
var a: [Int] = [1, 2, 3]
9+
10+
swap(&a[i], &a[j]) // no-warning
11+
12+
// expected-warning@+2{{modification requires exclusive access}}
13+
// expected-note@+1{{conflicting modification requires exclusive access}}
14+
takesTwoInouts(&a[i], &a[j])
15+
}
16+
17+
func missedSwapSuppression(_ i: Int, _ j: Int) {
18+
var a: [Int] = [1, 2, 3]
19+
20+
// We don't suppress when swap() is used as a value
21+
let mySwap: (inout Int, inout Int) -> () = swap
22+
23+
// expected-warning@+2{{modification requires exclusive access}}
24+
// expected-note@+1{{conflicting modification requires exclusive access}}
25+
mySwap(&a[i], &a[j])
26+
}
27+
28+
func dontSuppressUserSwap(_ i: Int, _ j: Int) {
29+
var a: [Int] = [1, 2, 3]
30+
31+
// Don't suppress on user-defined swap.
32+
func swap<T>(_ p1: inout T, _ p2: inout T) {
33+
return (p1, p2) = (p2, p1)
34+
}
35+
36+
// expected-warning@+2{{modification requires exclusive access}}
37+
// expected-note@+1{{conflicting modification requires exclusive access}}
38+
swap(&a[i], &a[j])
39+
}

0 commit comments

Comments
 (0)