@@ -124,6 +124,11 @@ static void describeObjCReason(const ValueDecl *VD, ObjCReason Reason) {
124
124
}
125
125
}
126
126
127
+ void ObjCReason::setAttrInvalid () const {
128
+ if (requiresAttr (kind))
129
+ getAttr ()->setInvalid ();
130
+ }
131
+
127
132
static void diagnoseTypeNotRepresentableInObjC (const DeclContext *DC,
128
133
Type T,
129
134
SourceRange TypeRange,
@@ -588,49 +593,61 @@ bool swift::isRepresentableInObjC(
588
593
// Accessors can only be @objc if the storage declaration is.
589
594
// Global computed properties may however @_cdecl their accessors.
590
595
auto storage = accessor->getStorage ();
591
- if (!storage->isObjC () && Reason != ObjCReason::ExplicitlyCDecl &&
592
- Reason != ObjCReason::WitnessToObjC &&
593
- Reason != ObjCReason::MemberOfObjCProtocol) {
594
- if (accessor->isGetter ()) {
596
+ bool storageIsObjC = storage->isObjC ()
597
+ || Reason == ObjCReason::ExplicitlyCDecl
598
+ || Reason == ObjCReason::WitnessToObjC
599
+ || Reason == ObjCReason::MemberOfObjCProtocol;
600
+
601
+ switch (accessor->getAccessorKind ()) {
602
+ case AccessorKind::DidSet:
603
+ case AccessorKind::WillSet: {
604
+ // willSet/didSet implementations are never exposed to objc, they are
605
+ // always directly dispatched from the synthesized setter.
606
+ diagnoseAndRemoveAttr (accessor, Reason.getAttr (),
607
+ diag::objc_observing_accessor)
608
+ .limitBehavior (behavior);
609
+ describeObjCReason (accessor, Reason);
610
+ return false ;
611
+ }
612
+
613
+ case AccessorKind::Get:
614
+ if (!storageIsObjC) {
595
615
auto error = isa<VarDecl>(storage)
596
616
? diag::objc_getter_for_nonobjc_property
597
617
: diag::objc_getter_for_nonobjc_subscript;
598
618
599
- accessor->diagnose (error).limitBehavior (behavior);
619
+ diagnoseAndRemoveAttr (accessor, Reason.getAttr (), error)
620
+ .limitBehavior (behavior);
600
621
describeObjCReason (accessor, Reason);
601
- } else if (accessor->isSetter ()) {
622
+ return false ;
623
+ }
624
+ return true ;
625
+
626
+ case AccessorKind::Set:
627
+ if (!storageIsObjC) {
602
628
auto error = isa<VarDecl>(storage)
603
629
? diag::objc_setter_for_nonobjc_property
604
630
: diag::objc_setter_for_nonobjc_subscript;
605
631
606
- accessor->diagnose (error).limitBehavior (behavior);
632
+ diagnoseAndRemoveAttr (accessor, Reason.getAttr (), error)
633
+ .limitBehavior (behavior);
607
634
describeObjCReason (accessor, Reason);
635
+ return false ;
608
636
}
609
- return false ;
610
- }
611
-
612
- switch (accessor->getAccessorKind ()) {
613
- case AccessorKind::DidSet:
614
- case AccessorKind::WillSet:
615
- // willSet/didSet implementations are never exposed to objc, they are
616
- // always directly dispatched from the synthesized setter.
617
- accessor->diagnose (diag::objc_observing_accessor).limitBehavior (behavior);
618
- describeObjCReason (accessor, Reason);
619
- return false ;
620
-
621
- case AccessorKind::Get:
622
- case AccessorKind::Set:
623
637
return true ;
624
638
625
639
case AccessorKind::Address:
626
640
case AccessorKind::MutableAddress:
627
- accessor->diagnose (diag::objc_addressor).limitBehavior (behavior);
641
+ diagnoseAndRemoveAttr (accessor, Reason.getAttr (), diag::objc_addressor)
642
+ .limitBehavior (behavior);
628
643
describeObjCReason (accessor, Reason);
629
644
return false ;
630
645
631
646
case AccessorKind::Read:
632
647
case AccessorKind::Modify:
633
- accessor->diagnose (diag::objc_coroutine_accessor).limitBehavior (behavior);
648
+ diagnoseAndRemoveAttr (accessor, Reason.getAttr (),
649
+ diag::objc_coroutine_accessor)
650
+ .limitBehavior (behavior);
634
651
describeObjCReason (accessor, Reason);
635
652
return false ;
636
653
}
@@ -1145,9 +1162,9 @@ static bool isMemberOfObjCMembersClass(const ValueDecl *VD) {
1145
1162
1146
1163
ObjCReason swift::objCReasonForObjCAttr (const ObjCAttr *attr) {
1147
1164
if (attr->getAddedByAccessNote ())
1148
- return ObjCReason::ExplicitlyObjCByAccessNote;
1165
+ return ObjCReason (ObjCReason ::ExplicitlyObjCByAccessNote, attr) ;
1149
1166
1150
- return ObjCReason::ExplicitlyObjC;
1167
+ return ObjCReason (ObjCReason ::ExplicitlyObjC, attr) ;
1151
1168
}
1152
1169
1153
1170
// A class is @objc if it does not have generic ancestry, and it either has
@@ -1325,18 +1342,22 @@ Optional<ObjCReason> shouldMarkAsObjC(const ValueDecl *VD, bool allowImplicit) {
1325
1342
//
1326
1343
// @IBInspectable and @GKInspectable imply @objc quietly in Swift 3
1327
1344
// (where they warn on failure) and loudly in Swift 4 (error on failure).
1328
- if (VD->getAttrs ().hasAttribute <IBOutletAttr>())
1329
- return ObjCReason (ObjCReason::ExplicitlyIBOutlet);
1330
- if (VD->getAttrs ().hasAttribute <IBActionAttr>())
1331
- return ObjCReason (ObjCReason::ExplicitlyIBAction);
1332
- if (VD->getAttrs ().hasAttribute <IBSegueActionAttr>())
1333
- return ObjCReason (ObjCReason::ExplicitlyIBSegueAction);
1334
- if (VD->getAttrs ().hasAttribute <IBInspectableAttr>())
1335
- return ObjCReason (ObjCReason::ExplicitlyIBInspectable);
1336
- if (VD->getAttrs ().hasAttribute <GKInspectableAttr>())
1337
- return ObjCReason (ObjCReason::ExplicitlyGKInspectable);
1338
- if (VD->getAttrs ().hasAttribute <NSManagedAttr>())
1339
- return ObjCReason (ObjCReason::ExplicitlyNSManaged);
1345
+ if (auto attr = VD->getAttrs ().getAttribute <IBOutletAttr>())
1346
+ return ObjCReason (ObjCReason::ExplicitlyIBOutlet, attr);
1347
+ if (auto attr = VD->getAttrs ().getAttribute <IBActionAttr>())
1348
+ return ObjCReason (ObjCReason::ExplicitlyIBAction, attr);
1349
+ if (auto attr = VD->getAttrs ().getAttribute <IBSegueActionAttr>())
1350
+ return ObjCReason (ObjCReason::ExplicitlyIBSegueAction, attr);
1351
+ if (auto attr = VD->getAttrs ().getAttribute <IBInspectableAttr>())
1352
+ return ObjCReason (ObjCReason::ExplicitlyIBInspectable, attr);
1353
+ if (auto attr = VD->getAttrs ().getAttribute <GKInspectableAttr>())
1354
+ return ObjCReason (ObjCReason::ExplicitlyGKInspectable, attr);
1355
+ if (auto attr = VD->getAttrs ().getAttribute <NSManagedAttr>()) {
1356
+ // Make sure the implicit DynamicAttr gets added before we potentially
1357
+ // disable this attribute.
1358
+ (void ) VD->isDynamic ();
1359
+ return ObjCReason (ObjCReason::ExplicitlyNSManaged, attr);
1360
+ }
1340
1361
// A member of an @objc protocol is implicitly @objc.
1341
1362
if (isMemberOfObjCProtocol) {
1342
1363
if (!VD->isProtocolRequirement ())
@@ -1389,7 +1410,7 @@ Optional<ObjCReason> shouldMarkAsObjC(const ValueDecl *VD, bool allowImplicit) {
1389
1410
" @objc " );
1390
1411
}
1391
1412
1392
- return ObjCReason (ObjCReason::ExplicitlyDynamic);
1413
+ return ObjCReason (ObjCReason::ExplicitlyDynamic, attr );
1393
1414
}
1394
1415
}
1395
1416
@@ -1584,17 +1605,23 @@ bool IsObjCRequest::evaluate(Evaluator &evaluator, ValueDecl *VD) const {
1584
1605
Optional<ForeignAsyncConvention> asyncConvention;
1585
1606
Optional<ForeignErrorConvention> errorConvention;
1586
1607
if (auto var = dyn_cast<VarDecl>(VD)) {
1587
- if (!isRepresentableInObjC (var, *isObjC))
1608
+ if (!isRepresentableInObjC (var, *isObjC)) {
1609
+ isObjC->setAttrInvalid ();
1588
1610
return false ;
1611
+ }
1589
1612
} else if (auto subscript = dyn_cast<SubscriptDecl>(VD)) {
1590
- if (!isRepresentableInObjC (subscript, *isObjC))
1613
+ if (!isRepresentableInObjC (subscript, *isObjC)) {
1614
+ isObjC->setAttrInvalid ();
1591
1615
return false ;
1616
+ }
1592
1617
} else if (isa<DestructorDecl>(VD)) {
1593
1618
// Destructors need no additional checking.
1594
1619
} else if (auto func = dyn_cast<AbstractFunctionDecl>(VD)) {
1595
1620
if (!isRepresentableInObjC (
1596
- func, *isObjC, asyncConvention, errorConvention))
1621
+ func, *isObjC, asyncConvention, errorConvention)) {
1622
+ isObjC->setAttrInvalid ();
1597
1623
return false ;
1624
+ }
1598
1625
}
1599
1626
1600
1627
// Note that this declaration is exposed to Objective-C.
0 commit comments