Skip to content

Commit f99bfba

Browse files
committed
Warn about modifications made by access notes
1 parent fafbb89 commit f99bfba

File tree

3 files changed

+119
-2
lines changed

3 files changed

+119
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5644,5 +5644,32 @@ ERROR(atomics_ordering_must_be_constant, none,
56445644
"ordering argument must be a static method or property of %0",
56455645
(Identifier))
56465646

5647+
//------------------------------------------------------------------------------
5648+
// MARK: access notes
5649+
//------------------------------------------------------------------------------
5650+
5651+
WARNING(attr_added_by_access_note, none,
5652+
"access note for %0 adds %select{attribute|modifier}1 '%2' to "
5653+
"this %3",
5654+
(StringRef, bool, StringRef, DescriptiveDeclKind))
5655+
NOTE(fixit_attr_added_by_access_note, none,
5656+
"add %select{attribute|modifier}0 explicitly to silence this warning",
5657+
(bool))
5658+
5659+
WARNING(attr_removed_by_access_note, none,
5660+
"access note for %0 removes %select{attribute|modifier}1 '%2' from "
5661+
"this %3",
5662+
(StringRef, bool, StringRef, DescriptiveDeclKind))
5663+
NOTE(fixit_attr_removed_by_access_note, none,
5664+
"remove %select{attribute|modifier}0 explicitly to silence this warning",
5665+
(bool))
5666+
5667+
WARNING(attr_objc_name_changed_by_access_note, none,
5668+
"access note for %0 changes the '@objc' name of this %1 to %2",
5669+
(StringRef, DescriptiveDeclKind, ObjCSelector))
5670+
WARNING(fixit_attr_objc_name_changed_by_access_note, none,
5671+
"change '@objc' name in source code explicitly to silence this warning",
5672+
())
5673+
56475674
#define UNDEFINE_DIAGNOSTIC_MACROS
56485675
#include "DefineDiagnosticMacros.h"

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,11 +1455,43 @@ static void addOrRemoveAttr(ValueDecl *VD, const AccessNotes &notes,
14551455
auto attr = VD->getAttrs().getAttribute<Attr>();
14561456
if (*expected == (attr != nullptr)) return;
14571457

1458+
auto diagnoseChangeByAccessNote =
1459+
[&](Diag<StringRef, bool, StringRef, DescriptiveDeclKind> diagID,
1460+
Diag<bool> fixitID) -> InFlightDiagnostic {
1461+
bool isModifier = attr->isDeclModifier();
1462+
Diagnostic warning(diagID, notes.reason, isModifier, attr->getAttrName(),
1463+
VD->getDescriptiveKind());
1464+
Diagnostic note(fixitID, isModifier);
1465+
1466+
ASTContext &ctx = VD->getASTContext();
1467+
1468+
if (attr->getLocation().isValid()) {
1469+
ctx.Diags.diagnose(attr->getLocation(), warning);
1470+
return ctx.Diags.diagnose(attr->getLocation(), note);
1471+
}
1472+
else {
1473+
ctx.Diags.diagnose(VD, warning);
1474+
return ctx.Diags.diagnose(VD->getAttributeInsertionLoc(isModifier), note);
1475+
}
1476+
};
1477+
14581478
if (*expected) {
14591479
attr = willCreate();
14601480
VD->getAttrs().add(attr);
1481+
1482+
SmallString<64> attrString;
1483+
llvm::raw_svector_ostream os(attrString);
1484+
attr->print(os, VD);
1485+
1486+
diagnoseChangeByAccessNote(diag::attr_added_by_access_note,
1487+
diag::fixit_attr_added_by_access_note)
1488+
.fixItInsert(VD->getAttributeInsertionLoc(attr->isDeclModifier()),
1489+
attrString);
14611490
} else {
14621491
VD->getAttrs().removeAttribute(attr);
1492+
diagnoseChangeByAccessNote(diag::attr_removed_by_access_note,
1493+
diag::fixit_attr_removed_by_access_note)
1494+
.fixItRemove(attr->getRangeWithAt());
14631495
}
14641496
}
14651497

@@ -1483,6 +1515,26 @@ static void applyAccessNote(ValueDecl *VD, const AccessNote &note,
14831515
}
14841516
else if (!attr->hasName()) {
14851517
attr->setName(*note.ObjCName, true);
1518+
ctx.Diags.diagnose(attr->getLocation(),
1519+
diag::attr_objc_name_changed_by_access_note,
1520+
notes.reason, VD->getDescriptiveKind(),
1521+
*note.ObjCName);
1522+
1523+
SmallString<64> newNameString;
1524+
llvm::raw_svector_ostream os(newNameString);
1525+
os << "(";
1526+
os << *note.ObjCName;
1527+
os << ")";
1528+
1529+
auto note =
1530+
ctx.Diags.diagnose(attr->getLocation(),
1531+
diag::fixit_attr_objc_name_changed_by_access_note);
1532+
1533+
if (attr->getLParenLoc().isValid())
1534+
note.fixItReplace({ attr->getLParenLoc(), attr->getRParenLoc() },
1535+
newNameString);
1536+
else
1537+
note.fixItInsertAfter(attr->getLocation(), newNameString);
14861538
}
14871539
else if (attr->getName() != *note.ObjCName) {
14881540
// TODO: diagnose conflict between explicit name in code and explicit

test/SILGen/objc_access_notes.swift

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

2-
// RUN: %target-swift-emit-silgen -module-name objc_thunks -Xllvm -sil-full-demangle -Xllvm -sil-print-debuginfo -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -emit-verbose-sil -swift-version 5 -access-notes %S/Inputs/objc_access_notes.accessnotes | %FileCheck %s
2+
// RUN: %target-swift-emit-silgen -module-name objc_thunks -Xllvm -sil-full-demangle -Xllvm -sil-print-debuginfo -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -emit-verbose-sil -swift-version 5 -access-notes %S/Inputs/objc_access_notes.accessnotes -verify | %FileCheck %s
3+
4+
// Verify that the access notes are necessary for the test to pass.
35
// RUN-X: not %target-swift-emit-silgen -module-name objc_thunks -Xllvm -sil-full-demangle -Xllvm -sil-print-debuginfo -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -emit-verbose-sil -swift-version 5 | %FileCheck %s
46

57
// REQUIRES: objc_interop
@@ -8,6 +10,8 @@ import gizmo
810
import ansible
911

1012
class Hoozit : Gizmo {
13+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this instance method}}
14+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
1115
func typical(_ x: Int, y: Gizmo) -> Gizmo { return y }
1216
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC7typical_1ySo5GizmoCSi_AGtFTo : $@convention(objc_method) (Int, Gizmo, Hoozit) -> @autoreleased Gizmo {
1317
// CHECK: bb0([[X:%.*]] : $Int, [[Y:%.*]] : @unowned $Gizmo, [[THIS:%.*]] : @unowned $Hoozit):
@@ -52,6 +56,8 @@ class Hoozit : Gizmo {
5256
// CHECK-NEXT: }
5357

5458
// NS_RETURNS_RETAINED by family (-copy)
59+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this instance method}}
60+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
5561
func copyFoo() -> Gizmo { return self }
5662
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC7copyFooSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
5763
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
@@ -66,6 +72,8 @@ class Hoozit : Gizmo {
6672
// CHECK-NEXT: }
6773

6874
// NS_RETURNS_RETAINED by family (-mutableCopy)
75+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this instance method}}
76+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
6977
func mutableCopyFoo() -> Gizmo { return self }
7078
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC14mutableCopyFooSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
7179
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
@@ -82,6 +90,8 @@ class Hoozit : Gizmo {
8290
// NS_RETURNS_RETAINED by family (-copy). This is different from Swift's
8391
// normal notion of CamelCase, but it's what Clang does, so we should match
8492
// it.
93+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this instance method}}
94+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
8595
func copy8() -> Gizmo { return self }
8696
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC5copy8So5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
8797
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
@@ -96,6 +106,8 @@ class Hoozit : Gizmo {
96106
// CHECK-NEXT: }
97107

98108
// NS_RETURNS_RETAINED by family (-copy)
109+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this instance method}}
110+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
99111
func makeDuplicate() -> Gizmo { return self }
100112
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC13makeDuplicateSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
101113
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
@@ -111,6 +123,8 @@ class Hoozit : Gizmo {
111123

112124
// Override the normal family conventions to make this non-consuming and
113125
// returning at +0.
126+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this instance method}}
127+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
114128
func initFoo() -> Gizmo { return self }
115129
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC7initFooSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo
116130
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
@@ -124,6 +138,8 @@ class Hoozit : Gizmo {
124138
// CHECK-NEXT: return [[RES]]
125139
// CHECK-NEXT: }
126140

141+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this property}}
142+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
127143
var typicalProperty: Gizmo
128144
// -- getter
129145
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC15typicalPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo {
@@ -174,6 +190,8 @@ class Hoozit : Gizmo {
174190
// CHECK: } // end sil function '$s11objc_thunks6HoozitC15typicalPropertySo5GizmoCvs'
175191

176192
// NS_RETURNS_RETAINED getter by family (-copy)
193+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this property}}
194+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
177195
var copyProperty: Gizmo
178196
// -- getter
179197
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC12copyPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo {
@@ -221,6 +239,8 @@ class Hoozit : Gizmo {
221239
// CHECK: destroy_value [[ARG1]]
222240
// CHECK: } // end sil function '$s11objc_thunks6HoozitC12copyPropertySo5GizmoCvs'
223241

242+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this property}}
243+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
224244
var roProperty: Gizmo { return self }
225245
// -- getter
226246
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC10roPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo {
@@ -238,6 +258,8 @@ class Hoozit : Gizmo {
238258
// -- no setter
239259
// CHECK-NOT: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC10roPropertySo5GizmoCvsTo
240260

261+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this property}}
262+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
241263
var rwProperty: Gizmo {
242264
get {
243265
return self
@@ -261,6 +283,8 @@ class Hoozit : Gizmo {
261283
// CHECK-NEXT: return
262284
// CHECK-NEXT: }
263285

286+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this property}}
287+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
264288
var copyRWProperty: Gizmo {
265289
get {
266290
return self
@@ -295,6 +319,8 @@ class Hoozit : Gizmo {
295319
// CHECK-NEXT: return
296320
// CHECK-NEXT: }
297321

322+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this property}}
323+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
298324
var initProperty: Gizmo
299325
// -- getter
300326
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC12initPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo {
@@ -323,6 +349,8 @@ class Hoozit : Gizmo {
323349
// CHECK-NEXT: return
324350
// CHECK-NEXT: }
325351

352+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this property}}
353+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
326354
var propComputed: Gizmo {
327355
// FIXME: Add a way to specify these names in an access note.
328356
@objc(initPropComputedGetter) get { return self }
@@ -379,6 +407,8 @@ class Hoozit : Gizmo {
379407
}
380408

381409
// Subscript
410+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this subscript}}
411+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
382412
subscript (i: Int) -> Hoozit {
383413
// Getter
384414
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitCyACSicigTo : $@convention(objc_method) (Int, Hoozit) -> @autoreleased Hoozit
@@ -424,6 +454,8 @@ class Wotsit<T> : Gizmo {
424454
// CHECK-NEXT: return [[RESULT]] : $()
425455
// CHECK-NEXT: }
426456
func plain() { }
457+
// expected-warning@-1 {{access note for fancy test suite adds attribute 'objc' to this instance method}}
458+
// expected-note@-2 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
427459

428460
func generic<U>(_ x: U) {}
429461

@@ -470,14 +502,20 @@ class Wotsit<T> : Gizmo {
470502
extension Hoozit {
471503
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC3intACSi_tcfcTo : $@convention(objc_method) (Int, @owned Hoozit) -> @owned Hoozit
472504
convenience init(int i: Int) { self.init(bellsOn: i) }
505+
// expected-warning@-1 {{access note for fancy test suite adds attribute 'objc' to this initializer}}
506+
// expected-note@-2 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
507+
// expected-warning@-3 {{access note for fancy test suite adds modifier 'dynamic' to this initializer}}
508+
// expected-note@-4 {{add modifier explicitly to silence this warning}} {{3-3=dynamic }}
473509

474510
// CHECK-LABEL: sil hidden [ossa] @$s11objc_thunks6HoozitC6doubleACSd_tcfC : $@convention(method) (Double, @thick Hoozit.Type) -> @owned Hoozit
475511
convenience init(double d: Double) {
476-
var x = X()
512+
var x = X() // expected-warning {{initialization of variable 'x' was never used}}
477513
self.init(int:Int(d))
478514
other()
479515
}
480516

517+
// expected-warning@+2 {{access note for fancy test suite adds attribute 'objc' to this instance method}}
518+
// expected-note@+1 {{add attribute explicitly to silence this warning}} {{3-3=@objc }}
481519
func foof() {}
482520
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC4foofyyFTo : $@convention(objc_method) (Hoozit) -> () {
483521

0 commit comments

Comments
 (0)