From b223ccbe91096aac4c7b9eb61965c3393b1d13a9 Mon Sep 17 00:00:00 2001 From: swift-ci Date: Fri, 15 Feb 2019 18:51:23 -0800 Subject: [PATCH] Merge pull request #22605 from brentdax/all-in-the-family --- include/swift/AST/Identifier.h | 8 ++ include/swift/AST/ObjCSelectorFamily.def | 29 ++++++ lib/AST/Identifier.cpp | 25 ++++++ lib/SIL/SILFunctionType.cpp | 108 ++++++++--------------- 4 files changed, 97 insertions(+), 73 deletions(-) create mode 100644 include/swift/AST/ObjCSelectorFamily.def diff --git a/include/swift/AST/Identifier.h b/include/swift/AST/Identifier.h index c2bf02719cefa..b799935cbecbd 100644 --- a/include/swift/AST/Identifier.h +++ b/include/swift/AST/Identifier.h @@ -592,6 +592,12 @@ class DeclName { "only for use within the debugger"); }; +enum class ObjCSelectorFamily : unsigned { + None, +#define OBJC_SELECTOR_FAMILY(LABEL, PREFIX) LABEL, +#include "swift/AST/ObjCSelectorFamily.def" +}; + /// Represents an Objective-C selector. class ObjCSelector { /// The storage for an Objective-C selector. @@ -656,6 +662,8 @@ class ObjCSelector { /// \param scratch Scratch space to use. StringRef getString(llvm::SmallVectorImpl &scratch) const; + ObjCSelectorFamily getSelectorFamily() const; + void *getOpaqueValue() const { return Storage.getOpaqueValue(); } static ObjCSelector getFromOpaqueValue(void *p) { return ObjCSelector(DeclName::getFromOpaqueValue(p)); diff --git a/include/swift/AST/ObjCSelectorFamily.def b/include/swift/AST/ObjCSelectorFamily.def new file mode 100644 index 0000000000000..4fa04ffa48719 --- /dev/null +++ b/include/swift/AST/ObjCSelectorFamily.def @@ -0,0 +1,29 @@ +//===--- ObjCSelectorFamily.def - Objective-C Selector Families - C++ ---*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// +// +// This file defines macros used for macro-metaprogramming with Objective-C +// selector families, categories of Objective-C methods with special ARC +// semantics. +// +//===----------------------------------------------------------------------===// + +#ifndef OBJC_SELECTOR_FAMILY +#define OBJC_SELECTOR_FAMILY(LABEL, PREFIX) +#endif + +OBJC_SELECTOR_FAMILY(Alloc, "alloc") +OBJC_SELECTOR_FAMILY(Copy, "copy") +OBJC_SELECTOR_FAMILY(Init, "init") +OBJC_SELECTOR_FAMILY(MutableCopy, "mutableCopy") +OBJC_SELECTOR_FAMILY(New, "new") + +#undef OBJC_SELECTOR_FAMILY diff --git a/lib/AST/Identifier.cpp b/lib/AST/Identifier.cpp index 0bef9fc2dc0d6..4ba266bdc70a8 100644 --- a/lib/AST/Identifier.cpp +++ b/lib/AST/Identifier.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ConvertUTF.h" +#include "clang/Basic/CharInfo.h" using namespace swift; void *DeclBaseName::SubscriptIdentifierData = @@ -199,6 +200,30 @@ ObjCSelector::ObjCSelector(ASTContext &ctx, unsigned numArgs, Storage = DeclName(ctx, Identifier(), pieces); } +ObjCSelectorFamily ObjCSelector::getSelectorFamily() const { + StringRef text = getSelectorPieces().front().get(); + while (!text.empty() && text[0] == '_') text = text.substr(1); + + // Does the given selector start with the given string as a prefix, in the + // sense of the selector naming conventions? + // This implementation matches the one used by + // clang::Selector::getMethodFamily, to make sure we behave the same as + // Clang ARC. We're not just calling that method here because it means + // allocating a clang::IdentifierInfo, which requires a Clang ASTContext. + auto hasPrefix = [](StringRef text, StringRef prefix) { + if (!text.startswith(prefix)) return false; + if (text.size() == prefix.size()) return true; + assert(text.size() > prefix.size()); + return !clang::isLowercase(text[prefix.size()]); + }; + + if (false) /*for #define purposes*/; +#define OBJC_SELECTOR_FAMILY(LABEL, PREFIX) \ + else if (hasPrefix(text, PREFIX)) return ObjCSelectorFamily::LABEL; +#include "swift/AST/ObjCSelectorFamily.def" + else return ObjCSelectorFamily::None; +} + StringRef ObjCSelector::getString(llvm::SmallVectorImpl &scratch) const { // Fast path for zero-argument selectors. if (getNumArgs() == 0) { diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp index e87b02c33a1d0..7b23ab2c5f781 100644 --- a/lib/SIL/SILFunctionType.cpp +++ b/lib/SIL/SILFunctionType.cpp @@ -29,7 +29,6 @@ #include "clang/AST/Attr.h" #include "clang/AST/DeclObjC.h" #include "clang/Analysis/DomainSpecific/CocoaConventions.h" -#include "clang/Basic/CharInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" @@ -221,7 +220,7 @@ enum class ConventionsKind : uint8_t { ObjCMethod = 2, CFunctionType = 3, CFunction = 4, - SelectorFamily = 5, + ObjCSelectorFamily = 5, Deallocator = 6, Capture = 7, }; @@ -1710,64 +1709,27 @@ static const clang::Decl *findClangMethod(ValueDecl *method) { // Selector Family SILFunctionTypes //===----------------------------------------------------------------------===// -/// Apply a macro FAMILY(Name, Prefix) to all ObjC selector families. -#define FOREACH_FAMILY(FAMILY) \ - FAMILY(Alloc, "alloc") \ - FAMILY(Copy, "copy") \ - FAMILY(Init, "init") \ - FAMILY(MutableCopy, "mutableCopy") \ - FAMILY(New, "new") - -namespace { - enum class SelectorFamily : unsigned { - None, -#define GET_LABEL(LABEL, PREFIX) LABEL, -FOREACH_FAMILY(GET_LABEL) -#undef GET_LABEL - }; -} // end anonymous namespace - /// Derive the ObjC selector family from an identifier. /// /// Note that this will never derive the Init family, which is too dangerous /// to leave to chance. Swift functions starting with "init" are always /// emitted as if they are part of the "none" family. -static SelectorFamily getSelectorFamily(Identifier name) { - StringRef text = name.get(); - while (!text.empty() && text[0] == '_') text = text.substr(1); - - // Does the given selector start with the given string as a prefix, in the - // sense of the selector naming conventions? - // This implementation matches the one used by - // clang::Selector::getMethodFamily, to make sure we behave the same as Clang - // ARC. We're not just calling that method here because it means allocating a - // clang::IdentifierInfo, which requires a Clang ASTContext. - auto hasPrefix = [](StringRef text, StringRef prefix) { - if (!text.startswith(prefix)) return false; - if (text.size() == prefix.size()) return true; - assert(text.size() > prefix.size()); - return !clang::isLowercase(text[prefix.size()]); - }; - - auto result = SelectorFamily::None; - if (false) /*for #define purposes*/; -#define CHECK_PREFIX(LABEL, PREFIX) \ - else if (hasPrefix(text, PREFIX)) result = SelectorFamily::LABEL; - FOREACH_FAMILY(CHECK_PREFIX) -#undef CHECK_PREFIX - - if (result == SelectorFamily::Init) - return SelectorFamily::None; +static ObjCSelectorFamily getObjCSelectorFamily(ObjCSelector name) { + auto result = name.getSelectorFamily(); + + if (result == ObjCSelectorFamily::Init) + return ObjCSelectorFamily::None; + return result; } /// Get the ObjC selector family a foreign SILDeclRef belongs to. -static SelectorFamily getSelectorFamily(SILDeclRef c) { +static ObjCSelectorFamily getObjCSelectorFamily(SILDeclRef c) { assert(c.isForeign); switch (c.kind) { case SILDeclRef::Kind::Func: { if (!c.hasDecl()) - return SelectorFamily::None; + return ObjCSelectorFamily::None; auto *FD = cast(c.getDecl()); if (auto accessor = dyn_cast(FD)) { @@ -1783,11 +1745,11 @@ static SelectorFamily getSelectorFamily(SILDeclRef c) { } } - return getSelectorFamily(FD->getObjCSelector().getSelectorPieces().front()); + return getObjCSelectorFamily(FD->getObjCSelector()); } case SILDeclRef::Kind::Initializer: case SILDeclRef::Kind::IVarInitializer: - return SelectorFamily::Init; + return ObjCSelectorFamily::Init; /// Currently IRGen wraps alloc/init methods into Swift constructors /// with Swift conventions. @@ -1796,7 +1758,7 @@ static SelectorFamily getSelectorFamily(SILDeclRef c) { case SILDeclRef::Kind::Destroyer: case SILDeclRef::Kind::Deallocator: case SILDeclRef::Kind::IVarDestroyer: - return SelectorFamily::None; + return ObjCSelectorFamily::None; case SILDeclRef::Kind::EnumElement: case SILDeclRef::Kind::GlobalAccessor: @@ -1810,12 +1772,12 @@ static SelectorFamily getSelectorFamily(SILDeclRef c) { namespace { -class SelectorFamilyConventions : public Conventions { - SelectorFamily Family; +class ObjCSelectorFamilyConventions : public Conventions { + ObjCSelectorFamily Family; public: - SelectorFamilyConventions(SelectorFamily family) - : Conventions(ConventionsKind::SelectorFamily), Family(family) {} + ObjCSelectorFamilyConventions(ObjCSelectorFamily family) + : Conventions(ConventionsKind::ObjCSelectorFamily), Family(family) {} ParameterConvention getIndirectParameter(unsigned index, const AbstractionPattern &type, @@ -1836,14 +1798,14 @@ class SelectorFamilyConventions : public Conventions { ResultConvention getResult(const TypeLowering &tl) const override { switch (Family) { - case SelectorFamily::Alloc: - case SelectorFamily::Copy: - case SelectorFamily::Init: - case SelectorFamily::MutableCopy: - case SelectorFamily::New: + case ObjCSelectorFamily::Alloc: + case ObjCSelectorFamily::Copy: + case ObjCSelectorFamily::Init: + case ObjCSelectorFamily::MutableCopy: + case ObjCSelectorFamily::New: return ResultConvention::Owned; - case SelectorFamily::None: + case ObjCSelectorFamily::None: // Defaults below. break; } @@ -1860,7 +1822,7 @@ class SelectorFamilyConventions : public Conventions { ParameterConvention getDirectSelfParameter(const AbstractionPattern &type) const override { - if (Family == SelectorFamily::Init) + if (Family == ObjCSelectorFamily::Init) return ParameterConvention::Direct_Owned; return ObjCSelfConvention; } @@ -1872,21 +1834,21 @@ class SelectorFamilyConventions : public Conventions { } static bool classof(const Conventions *C) { - return C->getKind() == ConventionsKind::SelectorFamily; + return C->getKind() == ConventionsKind::ObjCSelectorFamily; } }; } // end anonymous namespace static CanSILFunctionType -getSILFunctionTypeForSelectorFamily(SILModule &M, SelectorFamily family, - CanAnyFunctionType origType, - CanAnyFunctionType substInterfaceType, - AnyFunctionType::ExtInfo extInfo, - const ForeignInfo &foreignInfo, - Optional constant) { +getSILFunctionTypeForObjCSelectorFamily(SILModule &M, ObjCSelectorFamily family, + CanAnyFunctionType origType, + CanAnyFunctionType substInterfaceType, + AnyFunctionType::ExtInfo extInfo, + const ForeignInfo &foreignInfo, + Optional constant) { return getSILFunctionType(M, AbstractionPattern(origType), substInterfaceType, - extInfo, SelectorFamilyConventions(family), + extInfo, ObjCSelectorFamilyConventions(family), foreignInfo, constant, constant, /*requirement subs*/None, /*witnessMethodConformance=*/None); @@ -1967,10 +1929,10 @@ getUncachedSILFunctionTypeForConstant(SILModule &M, // If the decl belongs to an ObjC method family, use that family's // ownership conventions. - return getSILFunctionTypeForSelectorFamily(M, getSelectorFamily(constant), - origLoweredInterfaceType, - origLoweredInterfaceType, - extInfo, foreignInfo, constant); + return getSILFunctionTypeForObjCSelectorFamily( + M, getObjCSelectorFamily(constant), + origLoweredInterfaceType, origLoweredInterfaceType, + extInfo, foreignInfo, constant); } CanSILFunctionType TypeConverter::