Skip to content

Commit fafbb89

Browse files
committed
Apply access notes
1 parent ccf244b commit fafbb89

File tree

5 files changed

+105
-22
lines changed

5 files changed

+105
-22
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2311,6 +2311,25 @@ class SpecializeAttrTargetDeclRequest
23112311
bool isCached() const { return true; }
23122312
};
23132313

2314+
/// Looks up and applies the access note for a given declaration.
2315+
class ApplyAccessNoteRequest
2316+
: public SimpleRequest<ApplyAccessNoteRequest,
2317+
evaluator::SideEffect(ValueDecl *),
2318+
RequestFlags::Cached> {
2319+
public:
2320+
using SimpleRequest::SimpleRequest;
2321+
2322+
private:
2323+
friend SimpleRequest;
2324+
2325+
evaluator::SideEffect evaluate(Evaluator &evaluator, ValueDecl *VD) const;
2326+
2327+
public:
2328+
// Cached.
2329+
bool isCached() const { return true; }
2330+
};
2331+
2332+
23142333
class TypeCheckSourceFileRequest
23152334
: public SimpleRequest<
23162335
TypeCheckSourceFileRequest, evaluator::SideEffect(SourceFile *),

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ SWIFT_REQUEST(TypeChecker, AbstractGenericSignatureRequest,
2020
SmallVector<GenericTypeParamType *, 2>,
2121
SmallVector<Requirement, 2>),
2222
Cached, NoLocationInfo)
23+
SWIFT_REQUEST(TypeChecker, ApplyAccessNoteRequest,
24+
evaluator::SideEffect(ValueDecl *), Cached, NoLocationInfo)
2325
SWIFT_REQUEST(TypeChecker, AttachedResultBuilderRequest,
2426
CustomAttr *(ValueDecl *), Cached, NoLocationInfo)
2527
SWIFT_REQUEST(TypeChecker, AttachedPropertyWrapperTypeRequest,

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,9 @@ static void markAsObjC(ValueDecl *D, ObjCReason reason,
14721472

14731473

14741474
bool IsObjCRequest::evaluate(Evaluator &evaluator, ValueDecl *VD) const {
1475+
// Access notes may add attributes that affect this calculus.
1476+
(void)evaluateOrDefault(evaluator, ApplyAccessNoteRequest{VD}, {});
1477+
14751478
auto dc = VD->getDeclContext();
14761479
Optional<ObjCReason> isObjC;
14771480
if (dc->getSelfClassDecl() && !isa<TypeDecl>(VD)) {

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "TypeCheckObjC.h"
2727
#include "TypeCheckType.h"
2828
#include "MiscDiagnostics.h"
29+
#include "swift/AST/AccessNotes.h"
2930
#include "swift/AST/AccessScope.h"
3031
#include "swift/AST/ASTPrinter.h"
3132
#include "swift/AST/ASTVisitor.h"
@@ -1445,6 +1446,59 @@ void TypeChecker::diagnoseDuplicateCaptureVars(CaptureListExpr *expr) {
14451446
diagnoseDuplicateDecls(captureListVars);
14461447
}
14471448

1449+
template <typename Attr>
1450+
static void addOrRemoveAttr(ValueDecl *VD, const AccessNotes &notes,
1451+
Optional<bool> expected,
1452+
llvm::function_ref<Attr*()> willCreate) {
1453+
if (!expected) return;
1454+
1455+
auto attr = VD->getAttrs().getAttribute<Attr>();
1456+
if (*expected == (attr != nullptr)) return;
1457+
1458+
if (*expected) {
1459+
attr = willCreate();
1460+
VD->getAttrs().add(attr);
1461+
} else {
1462+
VD->getAttrs().removeAttribute(attr);
1463+
}
1464+
}
1465+
1466+
static void applyAccessNote(ValueDecl *VD, const AccessNote &note,
1467+
const AccessNotes &notes) {
1468+
ASTContext &ctx = VD->getASTContext();
1469+
1470+
addOrRemoveAttr<ObjCAttr>(VD, notes, note.ObjC, [&]() {
1471+
return ObjCAttr::create(ctx, note.ObjCName, true);
1472+
});
1473+
1474+
addOrRemoveAttr<DynamicAttr>(VD, notes, note.Dynamic, [&]{
1475+
return new (ctx) DynamicAttr(true);
1476+
});
1477+
1478+
if (note.ObjCName) {
1479+
auto attr = VD->getAttrs().getAttribute<ObjCAttr>();
1480+
1481+
if (!attr) {
1482+
// TODO: diagnose use of ObjCName without ObjC: true
1483+
}
1484+
else if (!attr->hasName()) {
1485+
attr->setName(*note.ObjCName, true);
1486+
}
1487+
else if (attr->getName() != *note.ObjCName) {
1488+
// TODO: diagnose conflict between explicit name in code and explicit
1489+
// name in access note
1490+
}
1491+
}
1492+
}
1493+
1494+
evaluator::SideEffect
1495+
ApplyAccessNoteRequest::evaluate(Evaluator &evaluator, ValueDecl *VD) const {
1496+
AccessNotes &notes = VD->getModuleContext()->getAccessNotes();
1497+
if (auto note = notes.lookup(VD))
1498+
applyAccessNote(VD, *note.get(), notes);
1499+
return {};
1500+
}
1501+
14481502
namespace {
14491503
class DeclChecker : public DeclVisitor<DeclChecker> {
14501504
public:
@@ -1466,7 +1520,11 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
14661520
FrontendStatsTracer StatsTracer(getASTContext().Stats,
14671521
"typecheck-decl", decl);
14681522
PrettyStackTraceDecl StackTrace("type-checking", decl);
1469-
1523+
1524+
if (auto VD = dyn_cast<ValueDecl>(decl))
1525+
(void)evaluateOrDefault(VD->getASTContext().evaluator,
1526+
ApplyAccessNoteRequest{VD}, {});
1527+
14701528
DeclVisitor<DeclChecker>::visit(decl);
14711529

14721530
TypeChecker::checkUnsupportedProtocolType(decl);

test/SILGen/objc_access_notes.swift

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import gizmo
88
import ansible
99

1010
class Hoozit : Gizmo {
11-
@objc func typical(_ x: Int, y: Gizmo) -> Gizmo { return y }
11+
func typical(_ x: Int, y: Gizmo) -> Gizmo { return y }
1212
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC7typical_1ySo5GizmoCSi_AGtFTo : $@convention(objc_method) (Int, Gizmo, Hoozit) -> @autoreleased Gizmo {
1313
// CHECK: bb0([[X:%.*]] : $Int, [[Y:%.*]] : @unowned $Gizmo, [[THIS:%.*]] : @unowned $Hoozit):
1414
// CHECK-NEXT: [[Y_COPY:%.*]] = copy_value [[Y]]
@@ -17,12 +17,12 @@ class Hoozit : Gizmo {
1717
// CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
1818
// CHECK-NEXT: // function_ref objc_thunks.Hoozit.typical
1919
// CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$s11objc_thunks6HoozitC7typical_1ySo5GizmoCSi_AGtF : $@convention(method) (Int, @guaranteed Gizmo, @guaranteed Hoozit) -> @owned Gizmo
20-
// CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[X]], [[BORROWED_Y_COPY]], [[BORROWED_THIS_COPY]]) {{.*}} line:[[@LINE-9]]:14:auto_gen
20+
// CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[X]], [[BORROWED_Y_COPY]], [[BORROWED_THIS_COPY]]) {{.*}} line:[[@LINE-9]]:8:auto_gen
2121
// CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]]
2222
// CHECK-NEXT: end_borrow [[BORROWED_Y_COPY]]
2323
// CHECK-NEXT: destroy_value [[THIS_COPY]] : $Hoozit
2424
// CHECK-NEXT: destroy_value [[Y_COPY]]
25-
// CHECK-NEXT: return [[RES]] : $Gizmo{{.*}} line:[[@LINE-14]]:14:auto_gen
25+
// CHECK-NEXT: return [[RES]] : $Gizmo{{.*}} line:[[@LINE-14]]:8:auto_gen
2626
// CHECK-NEXT: } // end sil function '$s11objc_thunks6HoozitC7typical_1ySo5GizmoCSi_AGtFTo'
2727

2828
// NS_CONSUMES_SELF by inheritance
@@ -52,7 +52,7 @@ class Hoozit : Gizmo {
5252
// CHECK-NEXT: }
5353

5454
// NS_RETURNS_RETAINED by family (-copy)
55-
@objc func copyFoo() -> Gizmo { return self }
55+
func copyFoo() -> Gizmo { return self }
5656
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC7copyFooSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
5757
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
5858
// CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
@@ -66,7 +66,7 @@ class Hoozit : Gizmo {
6666
// CHECK-NEXT: }
6767

6868
// NS_RETURNS_RETAINED by family (-mutableCopy)
69-
@objc func mutableCopyFoo() -> Gizmo { return self }
69+
func mutableCopyFoo() -> Gizmo { return self }
7070
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC14mutableCopyFooSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
7171
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
7272
// CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
@@ -82,7 +82,7 @@ class Hoozit : Gizmo {
8282
// NS_RETURNS_RETAINED by family (-copy). This is different from Swift's
8383
// normal notion of CamelCase, but it's what Clang does, so we should match
8484
// it.
85-
@objc func copy8() -> Gizmo { return self }
85+
func copy8() -> Gizmo { return self }
8686
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC5copy8So5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
8787
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
8888
// CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
@@ -96,7 +96,7 @@ class Hoozit : Gizmo {
9696
// CHECK-NEXT: }
9797

9898
// NS_RETURNS_RETAINED by family (-copy)
99-
@objc(copyDuplicate) func makeDuplicate() -> Gizmo { return self }
99+
func makeDuplicate() -> Gizmo { return self }
100100
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC13makeDuplicateSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
101101
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
102102
// CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
@@ -111,7 +111,7 @@ class Hoozit : Gizmo {
111111

112112
// Override the normal family conventions to make this non-consuming and
113113
// returning at +0.
114-
@objc func initFoo() -> Gizmo { return self }
114+
func initFoo() -> Gizmo { return self }
115115
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC7initFooSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo
116116
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
117117
// CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
@@ -124,7 +124,7 @@ class Hoozit : Gizmo {
124124
// CHECK-NEXT: return [[RES]]
125125
// CHECK-NEXT: }
126126

127-
@objc var typicalProperty: Gizmo
127+
var typicalProperty: Gizmo
128128
// -- getter
129129
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC15typicalPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo {
130130
// CHECK: bb0([[SELF:%.*]] : @unowned $Hoozit):
@@ -158,7 +158,7 @@ class Hoozit : Gizmo {
158158
// CHECK: [[RES:%.*]] = apply [[FR]]([[VALUE_COPY]], [[BORROWED_THIS_COPY]])
159159
// CHECK: end_borrow [[BORROWED_THIS_COPY]]
160160
// CHECK: destroy_value [[THIS_COPY]]
161-
// CHECK: return [[RES]] : $(), loc {{.*}}, scope {{.*}} // id: {{.*}} line:[[@LINE-34]]:13:auto_gen
161+
// CHECK: return [[RES]] : $(), loc {{.*}}, scope {{.*}} // id: {{.*}} line:[[@LINE-34]]:7:auto_gen
162162
// CHECK: } // end sil function '$s11objc_thunks6HoozitC15typicalPropertySo5GizmoCvsTo'
163163

164164
// CHECK-LABEL: sil hidden [ossa] @$s11objc_thunks6HoozitC15typicalPropertySo5GizmoCvs
@@ -174,7 +174,7 @@ class Hoozit : Gizmo {
174174
// CHECK: } // end sil function '$s11objc_thunks6HoozitC15typicalPropertySo5GizmoCvs'
175175

176176
// NS_RETURNS_RETAINED getter by family (-copy)
177-
@objc var copyProperty: Gizmo
177+
var copyProperty: Gizmo
178178
// -- getter
179179
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC12copyPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo {
180180
// CHECK: bb0([[SELF:%.*]] : @unowned $Hoozit):
@@ -221,7 +221,7 @@ class Hoozit : Gizmo {
221221
// CHECK: destroy_value [[ARG1]]
222222
// CHECK: } // end sil function '$s11objc_thunks6HoozitC12copyPropertySo5GizmoCvs'
223223

224-
@objc var roProperty: Gizmo { return self }
224+
var roProperty: Gizmo { return self }
225225
// -- getter
226226
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC10roPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo {
227227
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
@@ -238,7 +238,7 @@ class Hoozit : Gizmo {
238238
// -- no setter
239239
// CHECK-NOT: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC10roPropertySo5GizmoCvsTo
240240

241-
@objc var rwProperty: Gizmo {
241+
var rwProperty: Gizmo {
242242
get {
243243
return self
244244
}
@@ -261,7 +261,7 @@ class Hoozit : Gizmo {
261261
// CHECK-NEXT: return
262262
// CHECK-NEXT: }
263263

264-
@objc var copyRWProperty: Gizmo {
264+
var copyRWProperty: Gizmo {
265265
get {
266266
return self
267267
}
@@ -295,7 +295,7 @@ class Hoozit : Gizmo {
295295
// CHECK-NEXT: return
296296
// CHECK-NEXT: }
297297

298-
@objc var initProperty: Gizmo
298+
var initProperty: Gizmo
299299
// -- getter
300300
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC12initPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo {
301301
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
@@ -323,7 +323,8 @@ class Hoozit : Gizmo {
323323
// CHECK-NEXT: return
324324
// CHECK-NEXT: }
325325

326-
@objc var propComputed: Gizmo {
326+
var propComputed: Gizmo {
327+
// FIXME: Add a way to specify these names in an access note.
327328
@objc(initPropComputedGetter) get { return self }
328329
@objc(initPropComputedSetter:) set {}
329330
}
@@ -378,7 +379,7 @@ class Hoozit : Gizmo {
378379
}
379380

380381
// Subscript
381-
@objc subscript (i: Int) -> Hoozit {
382+
subscript (i: Int) -> Hoozit {
382383
// Getter
383384
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitCyACSicigTo : $@convention(objc_method) (Int, Hoozit) -> @autoreleased Hoozit
384385
// CHECK: bb0([[I:%[0-9]+]] : $Int, [[SELF:%[0-9]+]] : @unowned $Hoozit):
@@ -422,7 +423,7 @@ class Wotsit<T> : Gizmo {
422423
// CHECK-NEXT: destroy_value [[SELF_COPY]] : $Wotsit<T>
423424
// CHECK-NEXT: return [[RESULT]] : $()
424425
// CHECK-NEXT: }
425-
@objc func plain() { }
426+
func plain() { }
426427

427428
func generic<U>(_ x: U) {}
428429

@@ -468,7 +469,7 @@ class Wotsit<T> : Gizmo {
468469
// Extension initializers, properties and methods need thunks too.
469470
extension Hoozit {
470471
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC3intACSi_tcfcTo : $@convention(objc_method) (Int, @owned Hoozit) -> @owned Hoozit
471-
@objc dynamic convenience init(int i: Int) { self.init(bellsOn: i) }
472+
convenience init(int i: Int) { self.init(bellsOn: i) }
472473

473474
// CHECK-LABEL: sil hidden [ossa] @$s11objc_thunks6HoozitC6doubleACSd_tcfC : $@convention(method) (Double, @thick Hoozit.Type) -> @owned Hoozit
474475
convenience init(double d: Double) {
@@ -477,7 +478,7 @@ extension Hoozit {
477478
other()
478479
}
479480

480-
@objc func foof() {}
481+
func foof() {}
481482
// CHECK-LABEL: sil hidden [thunk] [ossa] @$s11objc_thunks6HoozitC4foofyyFTo : $@convention(objc_method) (Hoozit) -> () {
482483

483484
var extensionProperty: Int { return 0 }
@@ -536,7 +537,7 @@ class DesignatedStubs : Gizmo {
536537
// CHECK-LABEL: sil hidden [ossa] @$s11objc_thunks15DesignatedStubsC7bellsOnACSgSi_tcfc
537538
// CHECK: string_literal utf8 "objc_thunks.DesignatedStubs"
538539
// CHECK: string_literal utf8 "init(bellsOn:)"
539-
// CHECK: string_literal utf8 "{{.*}}objc_thunks.swift"
540+
// CHECK: string_literal utf8 "{{.*}}objc_access_notes.swift"
540541
// CHECK: function_ref @$ss25_unimplementedInitializer9className04initD04file4line6columns5NeverOs12StaticStringV_A2JS2utF
541542
// CHECK: return
542543

0 commit comments

Comments
 (0)