Skip to content

Commit 54e1f83

Browse files
authored
Merge pull request #8772 from DougGregor/rdar-31408971
2 parents e9d6b48 + 5cf233b commit 54e1f83

File tree

7 files changed

+57
-21
lines changed

7 files changed

+57
-21
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3080,6 +3080,10 @@ ERROR(objc_extension_not_class,none,
30803080
// If you change this, also change enum ObjCReason
30813081
#define OBJC_ATTR_SELECT "select{marked @_cdecl|marked dynamic|marked @objc|marked @IBOutlet|marked @IBAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)}"
30823082

3083+
WARNING(attribute_meaningless_when_nonobjc,none,
3084+
"'@%0' attribute is meaningless on a property that cannot be "
3085+
"represented in Objective-C", (StringRef))
3086+
30833087
ERROR(objc_invalid_on_var,none,
30843088
"property cannot be %" OBJC_ATTR_SELECT "0 "
30853089
"because its type cannot be represented in Objective-C", (unsigned))

lib/Sema/TypeCheckDecl.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2366,8 +2366,10 @@ static Optional<ObjCReason> shouldMarkAsObjC(TypeChecker &TC,
23662366
// explicitly declared @objc.
23672367
if (VD->getAttrs().hasAttribute<ObjCAttr>())
23682368
return ObjCReason::ExplicitlyObjC;
2369-
// @IBOutlet, @IBAction, @IBInspectable, @NSManaged, and @GKInspectable
2370-
// imply @objc.
2369+
// @IBOutlet, @IBAction, @NSManaged, and @GKInspectable imply @objc.
2370+
//
2371+
// @IBInspectable and @GKInspectable imply @objc quietly in Swift 3
2372+
// (where they warn on failure) and loudly in Swift 4 (error on failure).
23712373
if (VD->getAttrs().hasAttribute<IBOutletAttr>())
23722374
return ObjCReason::ExplicitlyIBOutlet;
23732375
if (VD->getAttrs().hasAttribute<IBActionAttr>())
@@ -2735,7 +2737,7 @@ void swift::markAsObjC(TypeChecker &TC, ValueDecl *D,
27352737
// could be overridden by @nonobjc. If we see a @nonobjc and we are trying
27362738
// to add an @objc for whatever reason, diagnose an error.
27372739
if (auto *attr = D->getAttrs().getAttribute<NonObjCAttr>()) {
2738-
if (!shouldDiagnoseObjCReason(*isObjC))
2740+
if (!shouldDiagnoseObjCReason(*isObjC, TC.Context))
27392741
isObjC = ObjCReason::ImplicitlyObjC;
27402742

27412743
TC.diagnose(D->getStartLoc(), diag::nonobjc_not_allowed,
@@ -5113,7 +5115,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
51135115
// complain.
51145116
auto storageObjCAttr = storage->getAttrs().getAttribute<ObjCAttr>();
51155117
if (storageObjCAttr->isSwift3Inferred() &&
5116-
shouldDiagnoseObjCReason(*isObjC)) {
5118+
shouldDiagnoseObjCReason(*isObjC, TC.Context)) {
51175119
TC.diagnose(storage, diag::accessor_swift3_objc_inference,
51185120
storage->getDescriptiveKind(), storage->getFullName(),
51195121
isa<SubscriptDecl>(storage), FD->isSetter())
@@ -7282,6 +7284,24 @@ void TypeChecker::validateDecl(ValueDecl *D) {
72827284

72837285
markAsObjC(*this, VD, isObjC);
72847286

7287+
// Under the Swift 3 inference rules, if we have @IBInspectable or
7288+
// @GKInspectable but did not infer @objc, warn that the attribute is
7289+
if (!isObjC && Context.LangOpts.EnableSwift3ObjCInference) {
7290+
if (auto attr = VD->getAttrs().getAttribute<IBInspectableAttr>()) {
7291+
diagnose(attr->getLocation(),
7292+
diag::attribute_meaningless_when_nonobjc,
7293+
attr->getAttrName())
7294+
.fixItRemove(attr->getRange());
7295+
}
7296+
7297+
if (auto attr = VD->getAttrs().getAttribute<GKInspectableAttr>()) {
7298+
diagnose(attr->getLocation(),
7299+
diag::attribute_meaningless_when_nonobjc,
7300+
attr->getAttrName())
7301+
.fixItRemove(attr->getRange());
7302+
}
7303+
}
7304+
72857305
// Infer 'dynamic' before touching accessors.
72867306
inferDynamic(Context, VD);
72877307

lib/Sema/TypeCheckType.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3145,7 +3145,7 @@ static void describeObjCReason(TypeChecker &TC, const ValueDecl *VD,
31453145
static void diagnoseFunctionParamNotRepresentable(
31463146
TypeChecker &TC, const AbstractFunctionDecl *AFD, unsigned NumParams,
31473147
unsigned ParamIndex, const ParamDecl *P, ObjCReason Reason) {
3148-
if (!shouldDiagnoseObjCReason(Reason))
3148+
if (!shouldDiagnoseObjCReason(Reason, TC.Context))
31493149
return;
31503150

31513151
if (NumParams == 1) {
@@ -3171,7 +3171,7 @@ static bool isParamListRepresentableInObjC(TypeChecker &TC,
31713171
ObjCReason Reason) {
31723172
// If you change this function, you must add or modify a test in PrintAsObjC.
31733173

3174-
bool Diagnose = shouldDiagnoseObjCReason(Reason);
3174+
bool Diagnose = shouldDiagnoseObjCReason(Reason, TC.Context);
31753175

31763176
bool IsObjC = true;
31773177
unsigned NumParams = PL->size();
@@ -3180,7 +3180,7 @@ static bool isParamListRepresentableInObjC(TypeChecker &TC,
31803180

31813181
// Swift Varargs are not representable in Objective-C.
31823182
if (param->isVariadic()) {
3183-
if (Diagnose && shouldDiagnoseObjCReason(Reason)) {
3183+
if (Diagnose && shouldDiagnoseObjCReason(Reason, TC.Context)) {
31843184
TC.diagnose(param->getStartLoc(), diag::objc_invalid_on_func_variadic,
31853185
getObjCDiagnosticAttrKind(Reason))
31863186
.highlight(param->getSourceRange());
@@ -3267,7 +3267,7 @@ static bool checkObjCInExtensionContext(TypeChecker &tc,
32673267
static bool checkObjCWithGenericParams(TypeChecker &TC,
32683268
const AbstractFunctionDecl *AFD,
32693269
ObjCReason Reason) {
3270-
bool Diagnose = shouldDiagnoseObjCReason(Reason);
3270+
bool Diagnose = shouldDiagnoseObjCReason(Reason, TC.Context);
32713271

32723272
if (AFD->getGenericParams()) {
32733273
// Diagnose this problem, if asked to.
@@ -3288,7 +3288,7 @@ static bool checkObjCWithGenericParams(TypeChecker &TC,
32883288
static bool checkObjCInForeignClassContext(TypeChecker &TC,
32893289
const ValueDecl *VD,
32903290
ObjCReason Reason) {
3291-
bool Diagnose = shouldDiagnoseObjCReason(Reason);
3291+
bool Diagnose = shouldDiagnoseObjCReason(Reason, TC.Context);
32923292

32933293
auto type = VD->getDeclContext()->getDeclaredInterfaceType();
32943294
if (!type)
@@ -3356,7 +3356,7 @@ bool TypeChecker::isRepresentableInObjC(
33563356

33573357
// If you change this function, you must add or modify a test in PrintAsObjC.
33583358

3359-
bool Diagnose = shouldDiagnoseObjCReason(Reason);
3359+
bool Diagnose = shouldDiagnoseObjCReason(Reason, Context);
33603360

33613361
if (checkObjCInForeignClassContext(*this, AFD, Reason))
33623362
return false;
@@ -3688,7 +3688,7 @@ bool TypeChecker::isRepresentableInObjC(const VarDecl *VD, ObjCReason Reason) {
36883688
}
36893689
bool Result = T->isRepresentableIn(ForeignLanguage::ObjectiveC,
36903690
VD->getDeclContext());
3691-
bool Diagnose = shouldDiagnoseObjCReason(Reason);
3691+
bool Diagnose = shouldDiagnoseObjCReason(Reason, Context);
36923692

36933693
if (Result && checkObjCInExtensionContext(*this, VD, Diagnose))
36943694
return false;
@@ -3719,7 +3719,7 @@ bool TypeChecker::isRepresentableInObjC(const SubscriptDecl *SD,
37193719
ObjCReason Reason) {
37203720
// If you change this function, you must add or modify a test in PrintAsObjC.
37213721

3722-
bool Diagnose = shouldDiagnoseObjCReason(Reason);
3722+
bool Diagnose = shouldDiagnoseObjCReason(Reason, Context);
37233723

37243724
if (checkObjCInForeignClassContext(*this, SD, Reason))
37253725
return false;

lib/Sema/TypeChecker.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,8 @@ enum class ObjCReason {
551551

552552
/// Determine whether we should diagnose conflicts due to inferring @objc
553553
/// with this particular reason.
554-
static inline bool shouldDiagnoseObjCReason(ObjCReason reason) {
554+
static inline bool shouldDiagnoseObjCReason(ObjCReason reason,
555+
ASTContext &ctx) {
555556
switch(reason) {
556557
case ObjCReason::ExplicitlyCDecl:
557558
case ObjCReason::ExplicitlyDynamic:
@@ -563,11 +564,13 @@ static inline bool shouldDiagnoseObjCReason(ObjCReason reason) {
563564
case ObjCReason::OverridesObjC:
564565
case ObjCReason::WitnessToObjC:
565566
case ObjCReason::ImplicitlyObjC:
566-
case ObjCReason::ExplicitlyIBInspectable:
567-
case ObjCReason::ExplicitlyGKInspectable:
568567
case ObjCReason::MemberOfObjCExtension:
569568
return true;
570569

570+
case ObjCReason::ExplicitlyIBInspectable:
571+
case ObjCReason::ExplicitlyGKInspectable:
572+
return !ctx.LangOpts.EnableSwift3ObjCInference;
573+
571574
case ObjCReason::MemberOfObjCSubclass:
572575
case ObjCReason::MemberOfObjCMembersClass:
573576
case ObjCReason::Accessor:

test/attr/attr_objc.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,9 +1672,6 @@ class HasIBAction {
16721672
class HasIBInspectable {
16731673
@IBInspectable var goodProperty: AnyObject?
16741674
// CHECK: {{^}} @IBInspectable @objc var goodProperty: AnyObject?
1675-
1676-
@IBInspectable var badProperty: PlainStruct?
1677-
// expected-error@-1{{property cannot be marked @IBInspectable because its type cannot be represented in Objective-C}}
16781675
}
16791676

16801677
//===---
@@ -1685,9 +1682,6 @@ class HasIBInspectable {
16851682
class HasGKInspectable {
16861683
@GKInspectable var goodProperty: AnyObject?
16871684
// CHECK: {{^}} @GKInspectable @objc var goodProperty: AnyObject?
1688-
1689-
@GKInspectable var badProperty: PlainStruct?
1690-
// expected-error@-1{{property cannot be marked @GKInspectable because its type cannot be represented in Objective-C}}
16911685
}
16921686

16931687
//===---

test/attr/attr_objc_swift3_deprecated_uses.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
import Foundation
55

6+
struct SwiftStruct { }
7+
68
class ObjCSubclass : NSObject {
79
func foo() { } // expected-note 2{{add '@objc' to expose this instance method to Objective-C}}{{3-3=@objc }}
810
var bar: NSObject? = nil // expected-note 2{{add '@objc' to expose this var to Objective-C}}{{3-3=@objc }}
@@ -22,6 +24,9 @@ class ObjCSubclass : NSObject {
2224

2325
set { }
2426
}
27+
28+
@IBInspectable var ibvar: SwiftStruct = SwiftStruct() // expected-warning{{'@IBInspectable' attribute is meaningless on a property that cannot be represented in Objective-C}}{{3-18=}}
29+
@GKInspectable var gkvar: SwiftStruct = SwiftStruct() // expected-warning{{'@GKInspectable' attribute is meaningless on a property that cannot be represented in Objective-C}}{{3-18=}}
2530
}
2631

2732
class DynamicMembers {

test/attr/attr_objc_swift4.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,13 @@ func test(sc: ObjCSubclass, dm: DynamicMembers) {
2020
_ = #selector(getter: dm.bar)
2121
_ = #keyPath(DynamicMembers.bar)
2222
}
23+
24+
struct PlainStruct { }
25+
26+
class BadInSwift4 {
27+
@IBInspectable var badIBInspectable: PlainStruct?
28+
// expected-error@-1{{property cannot be marked @IBInspectable because its type cannot be represented in Objective-C}}
29+
30+
@GKInspectable var badGKInspectable: PlainStruct?
31+
// expected-error@-1{{property cannot be marked @GKInspectable because its type cannot be represented in Objective-C}}
32+
}

0 commit comments

Comments
 (0)