Skip to content

Commit 5f94043

Browse files
committed
[NFC] Move selector family logic to ObjCSelector
SILFunctionType has some logic which examines a selector and decides if it belongs to one of Objective-C’s special “method families”, like -alloc* and -copy*, which need to return a retained pointer instead of an autoreleased one. This change extracts most of that logic into SwiftAST as ObjCSelector::getSelectorFamily(), while leaving details specific to SIL’s use of it behind.
1 parent f944a54 commit 5f94043

File tree

3 files changed

+64
-59
lines changed

3 files changed

+64
-59
lines changed

include/swift/AST/Identifier.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,21 @@ class DeclName {
592592
"only for use within the debugger");
593593
};
594594

595+
/// Apply a macro FAMILY(Name, Prefix) to all ObjC selector families.
596+
#define FOREACH_OBJC_SELECTOR_FAMILY(FAMILY) \
597+
FAMILY(Alloc, "alloc") \
598+
FAMILY(Copy, "copy") \
599+
FAMILY(Init, "init") \
600+
FAMILY(MutableCopy, "mutableCopy") \
601+
FAMILY(New, "new")
602+
603+
enum class ObjCSelectorFamily : unsigned {
604+
None,
605+
#define GET_LABEL(LABEL, PREFIX) LABEL,
606+
FOREACH_OBJC_SELECTOR_FAMILY(GET_LABEL)
607+
#undef GET_LABEL
608+
};
609+
595610
/// Represents an Objective-C selector.
596611
class ObjCSelector {
597612
/// The storage for an Objective-C selector.
@@ -656,6 +671,8 @@ class ObjCSelector {
656671
/// \param scratch Scratch space to use.
657672
StringRef getString(llvm::SmallVectorImpl<char> &scratch) const;
658673

674+
ObjCSelectorFamily getSelectorFamily() const;
675+
659676
void *getOpaqueValue() const { return Storage.getOpaqueValue(); }
660677
static ObjCSelector getFromOpaqueValue(void *p) {
661678
return ObjCSelector(DeclName::getFromOpaqueValue(p));

lib/AST/Identifier.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/ADT/StringExtras.h"
1919
#include "llvm/Support/raw_ostream.h"
2020
#include "llvm/Support/ConvertUTF.h"
21+
#include "clang/Basic/CharInfo.h"
2122
using namespace swift;
2223

2324
void *DeclBaseName::SubscriptIdentifierData =
@@ -199,6 +200,31 @@ ObjCSelector::ObjCSelector(ASTContext &ctx, unsigned numArgs,
199200
Storage = DeclName(ctx, Identifier(), pieces);
200201
}
201202

203+
ObjCSelectorFamily ObjCSelector::getSelectorFamily() const {
204+
StringRef text = getSelectorPieces().front().get();
205+
while (!text.empty() && text[0] == '_') text = text.substr(1);
206+
207+
// Does the given selector start with the given string as a prefix, in the
208+
// sense of the selector naming conventions?
209+
// This implementation matches the one used by
210+
// clang::Selector::getMethodFamily, to make sure we behave the same as
211+
// Clang ARC. We're not just calling that method here because it means
212+
// allocating a clang::IdentifierInfo, which requires a Clang ASTContext.
213+
auto hasPrefix = [](StringRef text, StringRef prefix) {
214+
if (!text.startswith(prefix)) return false;
215+
if (text.size() == prefix.size()) return true;
216+
assert(text.size() > prefix.size());
217+
return !clang::isLowercase(text[prefix.size()]);
218+
};
219+
220+
if (false) /*for #define purposes*/;
221+
#define CHECK_PREFIX(LABEL, PREFIX) \
222+
else if (hasPrefix(text, PREFIX)) return ObjCSelectorFamily::LABEL;
223+
FOREACH_OBJC_SELECTOR_FAMILY(CHECK_PREFIX)
224+
#undef CHECK_PREFIX
225+
else return ObjCSelectorFamily::None;
226+
}
227+
202228
StringRef ObjCSelector::getString(llvm::SmallVectorImpl<char> &scratch) const {
203229
// Fast path for zero-argument selectors.
204230
if (getNumArgs() == 0) {

lib/SIL/SILFunctionType.cpp

Lines changed: 21 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include "clang/AST/Attr.h"
3030
#include "clang/AST/DeclObjC.h"
3131
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
32-
#include "clang/Basic/CharInfo.h"
3332
#include "llvm/Support/CommandLine.h"
3433
#include "llvm/Support/Compiler.h"
3534
#include "llvm/Support/Debug.h"
@@ -1710,64 +1709,27 @@ static const clang::Decl *findClangMethod(ValueDecl *method) {
17101709
// Selector Family SILFunctionTypes
17111710
//===----------------------------------------------------------------------===//
17121711

1713-
/// Apply a macro FAMILY(Name, Prefix) to all ObjC selector families.
1714-
#define FOREACH_FAMILY(FAMILY) \
1715-
FAMILY(Alloc, "alloc") \
1716-
FAMILY(Copy, "copy") \
1717-
FAMILY(Init, "init") \
1718-
FAMILY(MutableCopy, "mutableCopy") \
1719-
FAMILY(New, "new")
1720-
1721-
namespace {
1722-
enum class SelectorFamily : unsigned {
1723-
None,
1724-
#define GET_LABEL(LABEL, PREFIX) LABEL,
1725-
FOREACH_FAMILY(GET_LABEL)
1726-
#undef GET_LABEL
1727-
};
1728-
} // end anonymous namespace
1729-
17301712
/// Derive the ObjC selector family from an identifier.
17311713
///
17321714
/// Note that this will never derive the Init family, which is too dangerous
17331715
/// to leave to chance. Swift functions starting with "init" are always
17341716
/// emitted as if they are part of the "none" family.
1735-
static SelectorFamily getSelectorFamily(Identifier name) {
1736-
StringRef text = name.get();
1737-
while (!text.empty() && text[0] == '_') text = text.substr(1);
1738-
1739-
// Does the given selector start with the given string as a prefix, in the
1740-
// sense of the selector naming conventions?
1741-
// This implementation matches the one used by
1742-
// clang::Selector::getMethodFamily, to make sure we behave the same as Clang
1743-
// ARC. We're not just calling that method here because it means allocating a
1744-
// clang::IdentifierInfo, which requires a Clang ASTContext.
1745-
auto hasPrefix = [](StringRef text, StringRef prefix) {
1746-
if (!text.startswith(prefix)) return false;
1747-
if (text.size() == prefix.size()) return true;
1748-
assert(text.size() > prefix.size());
1749-
return !clang::isLowercase(text[prefix.size()]);
1750-
};
1751-
1752-
auto result = SelectorFamily::None;
1753-
if (false) /*for #define purposes*/;
1754-
#define CHECK_PREFIX(LABEL, PREFIX) \
1755-
else if (hasPrefix(text, PREFIX)) result = SelectorFamily::LABEL;
1756-
FOREACH_FAMILY(CHECK_PREFIX)
1757-
#undef CHECK_PREFIX
1758-
1759-
if (result == SelectorFamily::Init)
1760-
return SelectorFamily::None;
1717+
static ObjCSelectorFamily getSelectorFamily(ObjCSelector name) {
1718+
auto result = name.getSelectorFamily();
1719+
1720+
if (result == ObjCSelectorFamily::Init)
1721+
return ObjCSelectorFamily::None;
1722+
17611723
return result;
17621724
}
17631725

17641726
/// Get the ObjC selector family a foreign SILDeclRef belongs to.
1765-
static SelectorFamily getSelectorFamily(SILDeclRef c) {
1727+
static ObjCSelectorFamily getSelectorFamily(SILDeclRef c) {
17661728
assert(c.isForeign);
17671729
switch (c.kind) {
17681730
case SILDeclRef::Kind::Func: {
17691731
if (!c.hasDecl())
1770-
return SelectorFamily::None;
1732+
return ObjCSelectorFamily::None;
17711733

17721734
auto *FD = cast<FuncDecl>(c.getDecl());
17731735
if (auto accessor = dyn_cast<AccessorDecl>(FD)) {
@@ -1783,11 +1745,11 @@ static SelectorFamily getSelectorFamily(SILDeclRef c) {
17831745
}
17841746
}
17851747

1786-
return getSelectorFamily(FD->getObjCSelector().getSelectorPieces().front());
1748+
return getSelectorFamily(FD->getObjCSelector());
17871749
}
17881750
case SILDeclRef::Kind::Initializer:
17891751
case SILDeclRef::Kind::IVarInitializer:
1790-
return SelectorFamily::Init;
1752+
return ObjCSelectorFamily::Init;
17911753

17921754
/// Currently IRGen wraps alloc/init methods into Swift constructors
17931755
/// with Swift conventions.
@@ -1796,7 +1758,7 @@ static SelectorFamily getSelectorFamily(SILDeclRef c) {
17961758
case SILDeclRef::Kind::Destroyer:
17971759
case SILDeclRef::Kind::Deallocator:
17981760
case SILDeclRef::Kind::IVarDestroyer:
1799-
return SelectorFamily::None;
1761+
return ObjCSelectorFamily::None;
18001762

18011763
case SILDeclRef::Kind::EnumElement:
18021764
case SILDeclRef::Kind::GlobalAccessor:
@@ -1811,10 +1773,10 @@ static SelectorFamily getSelectorFamily(SILDeclRef c) {
18111773
namespace {
18121774

18131775
class SelectorFamilyConventions : public Conventions {
1814-
SelectorFamily Family;
1776+
ObjCSelectorFamily Family;
18151777

18161778
public:
1817-
SelectorFamilyConventions(SelectorFamily family)
1779+
SelectorFamilyConventions(ObjCSelectorFamily family)
18181780
: Conventions(ConventionsKind::SelectorFamily), Family(family) {}
18191781

18201782
ParameterConvention getIndirectParameter(unsigned index,
@@ -1836,14 +1798,14 @@ class SelectorFamilyConventions : public Conventions {
18361798

18371799
ResultConvention getResult(const TypeLowering &tl) const override {
18381800
switch (Family) {
1839-
case SelectorFamily::Alloc:
1840-
case SelectorFamily::Copy:
1841-
case SelectorFamily::Init:
1842-
case SelectorFamily::MutableCopy:
1843-
case SelectorFamily::New:
1801+
case ObjCSelectorFamily::Alloc:
1802+
case ObjCSelectorFamily::Copy:
1803+
case ObjCSelectorFamily::Init:
1804+
case ObjCSelectorFamily::MutableCopy:
1805+
case ObjCSelectorFamily::New:
18441806
return ResultConvention::Owned;
18451807

1846-
case SelectorFamily::None:
1808+
case ObjCSelectorFamily::None:
18471809
// Defaults below.
18481810
break;
18491811
}
@@ -1860,7 +1822,7 @@ class SelectorFamilyConventions : public Conventions {
18601822

18611823
ParameterConvention
18621824
getDirectSelfParameter(const AbstractionPattern &type) const override {
1863-
if (Family == SelectorFamily::Init)
1825+
if (Family == ObjCSelectorFamily::Init)
18641826
return ParameterConvention::Direct_Owned;
18651827
return ObjCSelfConvention;
18661828
}
@@ -1879,7 +1841,7 @@ class SelectorFamilyConventions : public Conventions {
18791841
} // end anonymous namespace
18801842

18811843
static CanSILFunctionType
1882-
getSILFunctionTypeForSelectorFamily(SILModule &M, SelectorFamily family,
1844+
getSILFunctionTypeForSelectorFamily(SILModule &M, ObjCSelectorFamily family,
18831845
CanAnyFunctionType origType,
18841846
CanAnyFunctionType substInterfaceType,
18851847
AnyFunctionType::ExtInfo extInfo,

0 commit comments

Comments
 (0)