Skip to content

Commit 042392f

Browse files
authored
Merge pull request #14825 from stephan-tolksdorf/SR-6065
[SIL] [SR-6065] Take into account ObjC selector name when determining method family
2 parents 30b2f05 + 2a5135b commit 042392f

File tree

4 files changed

+41
-82
lines changed

4 files changed

+41
-82
lines changed

lib/IRGen/GenObjC.cpp

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -487,21 +487,6 @@ namespace {
487487

488488
static constexpr struct ForGetter_t { } ForGetter{};
489489
static constexpr struct ForSetter_t { } ForSetter{};
490-
491-
#define FOREACH_FAMILY(FAMILY) \
492-
FAMILY(Alloc, "alloc") \
493-
FAMILY(Copy, "copy") \
494-
FAMILY(Init, "init") \
495-
FAMILY(MutableCopy, "mutableCopy") \
496-
FAMILY(New, "new")
497-
498-
// Note that these are in parallel with 'prefixes', below.
499-
enum class Family {
500-
None,
501-
#define GET_LABEL(LABEL, PREFIX) LABEL,
502-
FOREACH_FAMILY(GET_LABEL)
503-
#undef GET_LABEL
504-
};
505490

506491
Selector() = default;
507492

@@ -571,31 +556,6 @@ namespace {
571556
StringRef str() const {
572557
return Text;
573558
}
574-
575-
/// Return the family string of this selector.
576-
Family getFamily() const {
577-
StringRef text = str();
578-
while (!text.empty() && text[0] == '_') text = text.substr(1);
579-
580-
#define CHECK_PREFIX(LABEL, PREFIX) \
581-
if (hasPrefix(text, PREFIX)) return Family::LABEL;
582-
FOREACH_FAMILY(CHECK_PREFIX)
583-
#undef CHECK_PREFIX
584-
585-
return Family::None;
586-
}
587-
588-
private:
589-
/// Does the given selector start with the given string as a
590-
/// prefix, in the sense of the selector naming conventions?
591-
static bool hasPrefix(StringRef text, StringRef prefix) {
592-
if (!text.startswith(prefix)) return false;
593-
if (text.size() == prefix.size()) return true;
594-
assert(text.size() > prefix.size());
595-
return !clang::isLowercase(text[prefix.size()]);
596-
}
597-
598-
#undef FOREACH_FAMILY
599559
};
600560
} // end anonymous namespace
601561

lib/SIL/SILFunctionType.cpp

Lines changed: 24 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/ForeignInfo.h"
2424
#include "swift/AST/GenericEnvironment.h"
2525
#include "swift/AST/ProtocolConformance.h"
26+
#include "swift/Basic/StringExtras.h"
2627
#include "swift/SIL/SILModule.h"
2728
#include "swift/SIL/SILType.h"
2829
#include "clang/AST/Attr.h"
@@ -1723,19 +1724,12 @@ static SelectorFamily getSelectorFamily(Identifier name) {
17231724
StringRef text = name.get();
17241725
while (!text.empty() && text[0] == '_') text = text.substr(1);
17251726

1726-
/// Does the given selector start with the given string as a
1727-
/// prefix, in the sense of the selector naming conventions?
1728-
auto hasPrefix = [](StringRef text, StringRef prefix) {
1729-
if (!text.startswith(prefix)) return false;
1730-
if (text.size() == prefix.size()) return true;
1731-
assert(text.size() > prefix.size());
1732-
return !clang::isLowercase(text[prefix.size()]);
1733-
};
1727+
StringRef firstWord = camel_case::getFirstWord(text);
17341728

17351729
auto result = SelectorFamily::None;
17361730
if (false) /*for #define purposes*/;
17371731
#define CHECK_PREFIX(LABEL, PREFIX) \
1738-
else if (hasPrefix(text, PREFIX)) result = SelectorFamily::LABEL;
1732+
else if (firstWord == PREFIX) result = SelectorFamily::LABEL;
17391733
FOREACH_FAMILY(CHECK_PREFIX)
17401734
#undef CHECK_PREFIX
17411735

@@ -1744,61 +1738,49 @@ static SelectorFamily getSelectorFamily(Identifier name) {
17441738
return result;
17451739
}
17461740

1747-
/// Get the ObjC selector family a SILDeclRef implicitly belongs to.
1741+
/// Get the ObjC selector family a foreign SILDeclRef belongs to.
17481742
static SelectorFamily getSelectorFamily(SILDeclRef c) {
1743+
assert(c.isForeign);
17491744
switch (c.kind) {
17501745
case SILDeclRef::Kind::Func: {
17511746
if (!c.hasDecl())
17521747
return SelectorFamily::None;
17531748

17541749
auto *FD = cast<FuncDecl>(c.getDecl());
1755-
auto accessor = dyn_cast<AccessorDecl>(FD);
1756-
if (!accessor)
1757-
return getSelectorFamily(FD->getName());
1758-
1759-
switch (accessor->getAccessorKind()) {
1760-
case AccessorKind::IsGetter:
1761-
// Getter selectors can belong to families if their name begins with the
1762-
// wrong thing.
1763-
if (accessor->getStorage()->isObjC() || c.isForeign) {
1764-
auto declName = accessor->getStorage()->getBaseName();
1765-
switch (declName.getKind()) {
1766-
case DeclBaseName::Kind::Normal:
1767-
return getSelectorFamily(declName.getIdentifier());
1768-
case DeclBaseName::Kind::Subscript:
1769-
return SelectorFamily::None;
1770-
case DeclBaseName::Kind::Destructor:
1771-
return SelectorFamily::None;
1772-
}
1750+
if (auto accessor = dyn_cast<AccessorDecl>(FD)) {
1751+
switch (accessor->getAccessorKind()) {
1752+
case AccessorKind::IsGetter:
1753+
case AccessorKind::IsSetter:
1754+
break;
1755+
case AccessorKind::IsWillSet:
1756+
case AccessorKind::IsDidSet:
1757+
case AccessorKind::IsAddressor:
1758+
case AccessorKind::IsMutableAddressor:
1759+
case AccessorKind::IsMaterializeForSet:
1760+
llvm_unreachable("Unexpected AccessorKind of foreign FuncDecl");
17731761
}
1774-
return SelectorFamily::None;
1775-
1776-
// Other accessors are never selector family members.
1777-
case AccessorKind::IsSetter:
1778-
case AccessorKind::IsWillSet:
1779-
case AccessorKind::IsDidSet:
1780-
case AccessorKind::IsAddressor:
1781-
case AccessorKind::IsMutableAddressor:
1782-
case AccessorKind::IsMaterializeForSet:
1783-
return SelectorFamily::None;
17841762
}
1763+
1764+
return getSelectorFamily(FD->getObjCSelector().getSelectorPieces().front());
17851765
}
17861766
case SILDeclRef::Kind::Initializer:
1787-
case SILDeclRef::Kind::IVarInitializer:
1767+
case SILDeclRef::Kind::IVarInitializer:
17881768
return SelectorFamily::Init;
17891769

17901770
/// Currently IRGen wraps alloc/init methods into Swift constructors
17911771
/// with Swift conventions.
17921772
case SILDeclRef::Kind::Allocator:
17931773
/// These constants don't correspond to method families we care about yet.
1794-
case SILDeclRef::Kind::EnumElement:
17951774
case SILDeclRef::Kind::Destroyer:
17961775
case SILDeclRef::Kind::Deallocator:
1797-
case SILDeclRef::Kind::GlobalAccessor:
17981776
case SILDeclRef::Kind::IVarDestroyer:
1777+
return SelectorFamily::None;
1778+
1779+
case SILDeclRef::Kind::EnumElement:
1780+
case SILDeclRef::Kind::GlobalAccessor:
17991781
case SILDeclRef::Kind::DefaultArgGenerator:
18001782
case SILDeclRef::Kind::StoredPropertyInitializer:
1801-
return SelectorFamily::None;
1783+
llvm_unreachable("Unexpected Kind of foreign SILDeclRef");
18021784
}
18031785

18041786
llvm_unreachable("Unhandled SILDeclRefKind in switch.");

test/PrintAsObjC/classes.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ class NotObjC {}
226226
// CHECK-NEXT: - (void)initAllTheThings SWIFT_METHOD_FAMILY(none);
227227
// CHECK-NEXT: - (void)initTheOtherThings SWIFT_METHOD_FAMILY(none);
228228
// CHECK-NEXT: - (void)initializeEvenMoreThings;
229+
// CHECK-NEXT: + (Methods * _Nonnull)newWithFoo:(NSInteger)foo SWIFT_WARN_UNUSED_RESULT;
229230
// CHECK-NEXT: init
230231
// CHECK-NEXT: @end
231232
@objc class Methods {
@@ -286,6 +287,8 @@ class NotObjC {}
286287
@objc func initAllTheThings() {}
287288
@objc(initTheOtherThings) func setUpOtherThings() {}
288289
@objc func initializeEvenMoreThings() {}
290+
291+
@objc(newWithFoo:) class func make(foo: Int) -> Methods { return Methods() }
289292
}
290293

291294
typealias AliasForNSRect = NSRect

test/SILGen/objc_thunks.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,20 @@ class Hoozit : Gizmo {
5757
// CHECK-NEXT: return [[RES]]
5858
// CHECK-NEXT: }
5959

60+
// NS_RETURNS_RETAINED by family (-copy)
61+
@objc(copyDuplicate) func makeDuplicate() -> Gizmo { return self }
62+
// CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC13makeDuplicateSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
63+
// CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
64+
// CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
65+
// CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
66+
// CHECK-NEXT: // function_ref
67+
// CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC13makeDuplicateSo5GizmoCyF : $@convention(method) (@guaranteed Hoozit) -> @owned Gizmo
68+
// CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[BORROWED_THIS_COPY]])
69+
// CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
70+
// CHECK-NEXT: destroy_value [[THIS_COPY]]
71+
// CHECK-NEXT: return [[RES]]
72+
// CHECK-NEXT: }
73+
6074
// Override the normal family conventions to make this non-consuming and
6175
// returning at +0.
6276
@objc func initFoo() -> Gizmo { return self }

0 commit comments

Comments
 (0)