Switch ValueDecl::getObjCSelector() and friends over to ObjCSelector.

Formatting names into strings repeatedly, and using those for semantic
analysis, is generally considered poor form. Additionally, use the
camelCase utilities to perform the string manipulation we need, and
cache results on the ObjCAttr so we don't repeatedly do string
manipulation.

Swift SVN r16334
This commit is contained in:
Doug Gregor
2014-04-14 22:02:51 +00:00
parent 204c7006c4
commit 53b84c121e
9 changed files with 157 additions and 155 deletions

View File

@@ -3049,12 +3049,12 @@ public:
bool usesObjCGetterAndSetter() const; bool usesObjCGetterAndSetter() const;
/// Given that this is an Objective-C property or subscript declaration, /// Given that this is an Objective-C property or subscript declaration,
/// produce its getter selector in the given buffer (as UTF-8). /// produce its getter selector.
StringRef getObjCGetterSelector(SmallVectorImpl<char> &buffer) const; ObjCSelector getObjCGetterSelector() const;
/// Given that this is an Objective-C property or subscript declaration, /// Given that this is an Objective-C property or subscript declaration,
/// produce its setter selector in the given buffer (as UTF-8). /// produce its setter selector.
StringRef getObjCSetterSelector(SmallVectorImpl<char> &buffer) const; ObjCSelector getObjCSetterSelector() const;
AbstractStorageDecl *getOverriddenDecl() const { AbstractStorageDecl *getOverriddenDecl() const {
return OverriddenDecl.getPointer(); return OverriddenDecl.getPointer();
@@ -3373,7 +3373,7 @@ public:
} }
/// Retrieve the Objective-C selector that names this method. /// Retrieve the Objective-C selector that names this method.
StringRef getObjCSelector(SmallVectorImpl<char> &buffer) const; ObjCSelector getObjCSelector() const;
/// Determine the default argument kind and type for the given argument index /// Determine the default argument kind and type for the given argument index
/// in this declaration, which must be a function or constructor. /// in this declaration, which must be a function or constructor.
@@ -3722,9 +3722,8 @@ public:
/// return type. /// return type.
DynamicSelfType *getDynamicSelfInterface() const; DynamicSelfType *getDynamicSelfInterface() const;
/// Given that this is an Objective-C method declaration, produce /// Given that this is an Objective-C method declaration, get its selector.
/// its selector in the given buffer (as UTF-8). ObjCSelector getObjCSelector() const;
StringRef getObjCSelector(SmallVectorImpl<char> &buffer) const;
void getLocalCaptures(SmallVectorImpl<CaptureInfo:: void getLocalCaptures(SmallVectorImpl<CaptureInfo::
LocalCaptureTy> &Result) const { LocalCaptureTy> &Result) const {
@@ -3955,9 +3954,8 @@ public:
/// \brief Get the type of the constructed object. /// \brief Get the type of the constructed object.
Type getResultType() const; Type getResultType() const;
/// Given that this is an Objective-C method declaration, produce /// Given that this is an Objective-C method declaration, get its selector.
/// its selector in the given buffer (as UTF-8). ObjCSelector getObjCSelector() const;
StringRef getObjCSelector(SmallVectorImpl<char> &buffer) const;
/// Get the type of the initializing constructor. /// Get the type of the initializing constructor.
Type getInitializerType() const { return InitializerType; } Type getInitializerType() const { return InitializerType; }
@@ -4075,7 +4073,7 @@ public:
/// Retrieve the Objective-C selector associated with the destructor. /// Retrieve the Objective-C selector associated with the destructor.
/// ///
/// This is always "dealloc". /// This is always "dealloc".
StringRef getObjCSelector(SmallVectorImpl<char> &buffer) const; ObjCSelector getObjCSelector() const;
static bool classof(const Decl *D) { static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Destructor; return D->getKind() == DeclKind::Destructor;

View File

@@ -474,8 +474,8 @@ ERROR(override_decl_extension,sema_tcd,none,
NOTE(overridden_here,sema_tcd,none, NOTE(overridden_here,sema_tcd,none,
"overridden declaration is here", ()) "overridden declaration is here", ())
ERROR(override_objc_type_mismatch_method,sema_tcd,none, ERROR(override_objc_type_mismatch_method,sema_tcd,none,
"overriding method with selector '%0' has incompatible type %1", "overriding method with selector %0 has incompatible type %1",
(StringRef, Type)) (ObjCSelector, Type))
ERROR(override_objc_type_mismatch_subscript,sema_tcd,none, ERROR(override_objc_type_mismatch_subscript,sema_tcd,none,
"overriding %select{|indexed |keyed }0subscript with incompatible type " "overriding %select{|indexed |keyed }0subscript with incompatible type "
"%1", "%1",

View File

@@ -23,10 +23,16 @@
# error Must define IDENTIFIER_WITH_NAME(Name, IdStr) before including this x-macro file # error Must define IDENTIFIER_WITH_NAME(Name, IdStr) before including this x-macro file
#endif #endif
IDENTIFIER(atIndexedSubscript)
IDENTIFIER(dealloc)
IDENTIFIER(deinit) IDENTIFIER(deinit)
IDENTIFIER(forKeyedSubscript)
IDENTIFIER(init) IDENTIFIER(init)
IDENTIFIER(objectAtIndexedSubscript)
IDENTIFIER(objectForKeyedSubscript)
IDENTIFIER(self) IDENTIFIER(self)
IDENTIFIER(Self) IDENTIFIER(Self)
IDENTIFIER(setObject)
IDENTIFIER(subscript) IDENTIFIER(subscript)
IDENTIFIER_WITH_NAME(MatchOperator, "~=") IDENTIFIER_WITH_NAME(MatchOperator, "~=")

View File

@@ -1670,75 +1670,72 @@ void AbstractStorageDecl::setObservingAccessors(FuncDecl *Get,
Set->makeAccessor(this, AccessorKind::IsSetter); Set->makeAccessor(this, AccessorKind::IsSetter);
} }
StringRef AbstractStorageDecl:: ObjCSelector AbstractStorageDecl::getObjCGetterSelector() const {
getObjCGetterSelector(SmallVectorImpl<char> &buffer) const {
// If the getter has an @objc attribute with a name, use that. // If the getter has an @objc attribute with a name, use that.
if (auto getter = getGetter()) { if (auto getter = getGetter()) {
if (auto objcAttr = getter->getAttrs().getAttribute<ObjCAttr>()) { if (auto objcAttr = getter->getAttrs().getAttribute<ObjCAttr>()) {
if (auto name = objcAttr->getName()) if (auto name = objcAttr->getName())
return name->getString(buffer); return *name;
} }
} }
llvm::raw_svector_ostream out(buffer);
// Subscripts use a specific selector. // Subscripts use a specific selector.
auto &ctx = getASTContext();
if (auto *SD = dyn_cast<SubscriptDecl>(this)) { if (auto *SD = dyn_cast<SubscriptDecl>(this)) {
switch (SD->getObjCSubscriptKind()) { switch (SD->getObjCSubscriptKind()) {
case ObjCSubscriptKind::None: case ObjCSubscriptKind::None:
llvm_unreachable("Not an Objective-C subscript"); llvm_unreachable("Not an Objective-C subscript");
case ObjCSubscriptKind::Indexed: case ObjCSubscriptKind::Indexed:
out << "objectAtIndexedSubscript:"; return ObjCSelector(ctx, 1, ctx.Id_objectAtIndexedSubscript);
break;
case ObjCSubscriptKind::Keyed: case ObjCSubscriptKind::Keyed:
out << "objectForKeyedSubscript:"; return ObjCSelector(ctx, 1, ctx.Id_objectForKeyedSubscript);
break;
} }
return out.str();
} }
// The getter selector is the property name itself. // The getter selector is the property name itself.
return getName().str(); return ObjCSelector(ctx, 0, getName());
} }
StringRef AbstractStorageDecl::getObjCSetterSelector(SmallVectorImpl<char> &buffer) const { ObjCSelector AbstractStorageDecl::getObjCSetterSelector() const {
// If the setter has an @objc attribute with a name, use that. // If the setter has an @objc attribute with a name, use that.
if (auto setter = getSetter()) { auto setter = getSetter();
if (auto objcAttr = setter->getAttrs().getAttribute<ObjCAttr>()) { auto objcAttr = setter ? setter->getAttrs().getAttribute<ObjCAttr>()
: nullptr;
if (objcAttr) {
if (auto name = objcAttr->getName()) if (auto name = objcAttr->getName())
return name->getString(buffer); return *name;
} }
}
llvm::raw_svector_ostream out(buffer);
// Subscripts use a specific selector. // Subscripts use a specific selector.
auto &ctx = getASTContext();
if (auto *SD = dyn_cast<SubscriptDecl>(this)) { if (auto *SD = dyn_cast<SubscriptDecl>(this)) {
switch (SD->getObjCSubscriptKind()) { switch (SD->getObjCSubscriptKind()) {
case ObjCSubscriptKind::None: case ObjCSubscriptKind::None:
llvm_unreachable("Not an Objective-C subscript"); llvm_unreachable("Not an Objective-C subscript");
case ObjCSubscriptKind::Indexed: case ObjCSubscriptKind::Indexed:
out << "setObject:atIndexedSubscript:"; return ObjCSelector(ctx, 2,
break; { ctx.Id_setObject, ctx.Id_atIndexedSubscript });
case ObjCSubscriptKind::Keyed: case ObjCSubscriptKind::Keyed:
out << "setObject:forKeyedSubscript:"; return ObjCSelector(ctx, 2,
break; { ctx.Id_setObject, ctx.Id_forKeyedSubscript });
} }
return out.str();
} }
// The setter selector for, e.g., 'fooBar' is 'setFooBar:', with the // The setter selector for, e.g., 'fooBar' is 'setFooBar:', with the
// property name capitalized and preceded by 'set'. // property name capitalized and preceded by 'set'.
StringRef name = getName().str(); llvm::SmallString<16> scratch1, scratch2;
assert(name.size() >= 1 && "empty var name?!"); scratch1 += "set";
scratch1 += camel_case::toSentencecase(getName().str(), scratch2);
out << "set" << clang::toUppercase(name[0]) auto result = ObjCSelector(ctx, 1, ctx.getIdentifier(scratch1));
<< name.slice(1, name.size()) << ':';
return out.str(); // Cache the result, so we don't perform string manipulation again.
if (objcAttr)
const_cast<ObjCAttr *>(objcAttr)->setName(result);
return result;
} }
SourceLoc AbstractStorageDecl::getOverrideLoc() const { SourceLoc AbstractStorageDecl::getOverrideLoc() const {
@@ -2130,14 +2127,13 @@ SourceRange AbstractFunctionDecl::getBodySourceRange() const {
} }
} }
StringRef AbstractFunctionDecl::getObjCSelector( ObjCSelector AbstractFunctionDecl::getObjCSelector() const {
SmallVectorImpl<char> &buffer) const {
if (auto func = dyn_cast<FuncDecl>(this)) if (auto func = dyn_cast<FuncDecl>(this))
return func->getObjCSelector(buffer); return func->getObjCSelector();
if (auto ctor = dyn_cast<ConstructorDecl>(this)) if (auto ctor = dyn_cast<ConstructorDecl>(this))
return ctor->getObjCSelector(buffer); return ctor->getObjCSelector();
if (auto dtor = dyn_cast<DestructorDecl>(this)) if (auto dtor = dyn_cast<DestructorDecl>(this))
return dtor->getObjCSelector(buffer); return dtor->getObjCSelector();
llvm_unreachable("Unhandled AbstractFunctionDecl subclass"); llvm_unreachable("Unhandled AbstractFunctionDecl subclass");
} }
@@ -2333,27 +2329,21 @@ DynamicSelfType *FuncDecl::getDynamicSelfInterface() const {
} }
/// Produce the selector for this "Objective-C method" in the given buffer. /// Produce the selector for this "Objective-C method" in the given buffer.
StringRef FuncDecl::getObjCSelector(SmallVectorImpl<char> &buffer) const { ObjCSelector FuncDecl::getObjCSelector() const {
// For a getter or setter, go through the variable or subscript decl. // For a getter or setter, go through the variable or subscript decl.
if (isGetterOrSetter()) { if (isGetterOrSetter()) {
auto asd = cast<AbstractStorageDecl>(getAccessorStorageDecl()); auto asd = cast<AbstractStorageDecl>(getAccessorStorageDecl());
return isGetter() ? asd->getObjCGetterSelector(buffer) return isGetter() ? asd->getObjCGetterSelector()
: asd->getObjCSetterSelector(buffer); : asd->getObjCSetterSelector();
} }
// If there is an @objc attribute with a name, use that name. // If there is an @objc attribute with a name, use that name.
if (auto objc = getAttrs().getAttribute<ObjCAttr>()) { auto objc = getAttrs().getAttribute<ObjCAttr>();
if (objc) {
if (auto name = objc->getName()) if (auto name = objc->getName())
return name->getString(buffer); return *name;
} }
assert(buffer.empty());
llvm::raw_svector_ostream out(buffer);
// Start with the method name.
out << getName().str();
// We should always have exactly two levels of argument pattern. // We should always have exactly two levels of argument pattern.
auto argPatterns = getArgParamPatterns(); auto argPatterns = getArgParamPatterns();
assert(argPatterns.size() == 2); assert(argPatterns.size() == 2);
@@ -2361,44 +2351,46 @@ StringRef FuncDecl::getObjCSelector(SmallVectorImpl<char> &buffer) const {
auto tuple = dyn_cast<TuplePattern>(pattern); auto tuple = dyn_cast<TuplePattern>(pattern);
// If it's an empty tuple pattern, it's a nullary selector. // If it's an empty tuple pattern, it's a nullary selector.
auto &ctx = getASTContext();
if (tuple && tuple->getNumFields() == 0) if (tuple && tuple->getNumFields() == 0)
return out.str(); return ObjCSelector(ctx, 0, getName());
// Otherwise, it's at least a unary selector.
// If the first tuple element has a name, uppercase and emit it. // If it's a unary selector with no name for the first argument, we're done.
if (tuple && getASTContext().LangOpts.SplitPrepositions) {
llvm::SmallString<16> scratch;
if (auto named = dyn_cast<NamedPattern>(
tuple->getFields()[0].getPattern()
->getSemanticsProvidingPattern())) {
out << camel_case::toSentencecase(named->getBoundName().str(), scratch);
}
}
out << ':';
// If it's a unary selector, we're done.
if (!tuple) { if (!tuple) {
return out.str(); return ObjCSelector(ctx, 1, getName());
} }
// For every element except the first, add a selector component. // Attach the first parameter name to the base name.
auto firstPiece = getName();
bool didStringManipulation = false;
if (tuple && ctx.LangOpts.SplitPrepositions) {
llvm::SmallString<32> scratch1, scratch2;
scratch1 += firstPiece.str();
auto firstName = tuple->getFields()[0].getPattern()->getBoundName();
if (!firstName.empty()) {
scratch1 += camel_case::toSentencecase(firstName.str(), scratch2);
firstPiece = ctx.getIdentifier(scratch1);
}
}
// For every element beyond the first, add a selector component.
SmallVector<Identifier, 4> argumentNames;
argumentNames.push_back(firstPiece);
for (auto &elt : tuple->getFields().slice(1)) { for (auto &elt : tuple->getFields().slice(1)) {
auto eltPattern = elt.getPattern()->getSemanticsProvidingPattern(); auto eltPattern = elt.getPattern()->getSemanticsProvidingPattern();
argumentNames.push_back(eltPattern->getBoundName());
// Add a label to the selector component if there's a tag.
if (auto named = dyn_cast<NamedPattern>(eltPattern)) {
out << named->getBoundName().str();
} }
// Add the colon regardless. Yes, this can sometimes create a // Form the result.
// component that's just a colon, and that's actually a legal auto result = ObjCSelector(ctx, argumentNames.size(), argumentNames);
// selector.
out << ':';
}
return out.str(); // If we did any string manipulation, cache the result. We don't want to
// do that again.
if (didStringManipulation && objc)
const_cast<ObjCAttr *>(objc)->setName(result);
return result;
} }
SourceRange FuncDecl::getSourceRange() const { SourceRange FuncDecl::getSourceRange() const {
@@ -2460,66 +2452,70 @@ Type ConstructorDecl::getResultType() const {
return ArgTy; return ArgTy;
} }
/// Produce the selector for this "Objective-C method" in the given buffer. ObjCSelector ConstructorDecl::getObjCSelector() const {
StringRef
ConstructorDecl::getObjCSelector(SmallVectorImpl<char> &buffer) const {
// If there is an @objc attribute with a name, use that name. // If there is an @objc attribute with a name, use that name.
if (auto objc = getAttrs().getAttribute<ObjCAttr>()) { auto objc = getAttrs().getAttribute<ObjCAttr>();
if (objc) {
if (auto name = objc->getName()) if (auto name = objc->getName())
return name->getString(buffer); return *name;
} }
assert(buffer.empty()); auto &ctx = getASTContext();
llvm::raw_svector_ostream out(buffer);
// In the beginning, there was 'init'.
out << "init";
// If there are no parameters, this is just 'init()'. // If there are no parameters, this is just 'init()'.
auto tuple = cast<TuplePattern>(getArgParamPatterns()[1]); auto tuple = cast<TuplePattern>(getArgParamPatterns()[1]);
if (tuple->getNumFields() == 0) if (tuple->getNumFields() == 0)
return out.str(); return ObjCSelector(ctx, 0, ctx.Id_init);
// The first field is special: we uppercase the name. // The first field is special: we uppercase the name.
bool didStringManipulation = false;
SmallVector<Identifier, 4> selectorPieces;
const auto &firstElt = tuple->getFields()[0]; const auto &firstElt = tuple->getFields()[0];
auto firstPattern = firstElt.getPattern()->getSemanticsProvidingPattern(); auto firstPattern = firstElt.getPattern()->getSemanticsProvidingPattern();
if (auto firstNamed = dyn_cast<NamedPattern>(firstPattern)) { auto firstName = firstElt.getPattern()->getBoundName();
if (!firstNamed->getBoundName().empty()) { if (firstName.empty())
auto nameStr = firstNamed->getBoundName().str(); selectorPieces.push_back(ctx.Id_init);
out << (char)toupper(nameStr[0]); else {
out << nameStr.substr(1); llvm::SmallString<16> scratch1, scratch2;
scratch1 += "init";
scratch1 += camel_case::toSentencecase(firstName.str(), scratch2);
selectorPieces.push_back(ctx.getIdentifier(scratch1));
didStringManipulation = true;
} }
// If there is only a single parameter and its type is the empty tuple // If we have just one field, check whether this is actually a
// type, we're done: don't add the trailing colon. // nullary selector that we mapped to a single-element initializer to catch
// the name after "init".
if (tuple->getNumFields() == 1) { if (tuple->getNumFields() == 1) {
auto emptyTupleTy = TupleType::getEmpty(getASTContext()); if (firstPattern->hasType()) {
if (!firstPattern->getType()->isEqual(emptyTupleTy)) if (firstPattern->getType()->isEqual(TupleType::getEmpty(ctx))) {
out << ':'; auto result = ObjCSelector(ctx, 0, selectorPieces[0]);
return out.str();
}
// Continue with the remaining selectors. // Cache the name in the 'objc' attribute. We don't want to perform
out << ':'; // string manipulation again.
if (objc)
const_cast<ObjCAttr *>(objc)->setName(result);
return result;
}
} else {
// If we couldn't check the type, don't cache the result.
didStringManipulation = false;
}
} }
// For every remaining element, add a selector component. // For every remaining element, add a selector component.
for (auto &elt : tuple->getFields().slice(1)) { for (auto &elt : tuple->getFields().slice(1)) {
auto eltPattern = elt.getPattern()->getSemanticsProvidingPattern(); selectorPieces.push_back(elt.getPattern()->getBoundName());
// Add a label to the selector component if there's a tag.
if (auto named = dyn_cast<NamedPattern>(eltPattern)) {
out << named->getBoundName().str();
} }
// Add the colon regardless. Yes, this can sometimes create a auto result = ObjCSelector(ctx, selectorPieces.size(), selectorPieces);
// component that's just a colon, and that's actually a legal
// selector.
out << ':';
}
return out.str(); // Cache the name in the 'objc' attribute. We don't want to perform
// string manipulation again.
if (objc && didStringManipulation)
const_cast<ObjCAttr *>(objc)->setName(result);
return result;
} }
Type ConstructorDecl::getInitializerInterfaceType() { Type ConstructorDecl::getInitializerInterfaceType() {
@@ -2629,8 +2625,9 @@ ConstructorDecl::getDelegatingOrChainedInitKind(DiagnosticEngine *diags,
return finder.Kind; return finder.Kind;
} }
StringRef DestructorDecl::getObjCSelector(SmallVectorImpl<char> &buffer) const { ObjCSelector DestructorDecl::getObjCSelector() const {
return "dealloc"; auto &ctx = getASTContext();
return ObjCSelector(ctx, 0, ctx.Id_dealloc);
} }
SourceRange DestructorDecl::getSourceRange() const { SourceRange DestructorDecl::getSourceRange() const {

View File

@@ -312,18 +312,18 @@ namespace {
Selector() = default; Selector() = default;
Selector(FuncDecl *method) { Selector(FuncDecl *method) {
Text = method->getObjCSelector(Buffer); Text = method->getObjCSelector().getString(Buffer);
} }
Selector(ConstructorDecl *ctor) { Selector(ConstructorDecl *ctor) {
Text = ctor->getObjCSelector(Buffer); Text = ctor->getObjCSelector().getString(Buffer);
} }
Selector(ValueDecl *methodOrCtorOrDtor) { Selector(ValueDecl *methodOrCtorOrDtor) {
if (auto *method = dyn_cast<FuncDecl>(methodOrCtorOrDtor)) { if (auto *method = dyn_cast<FuncDecl>(methodOrCtorOrDtor)) {
Text = method->getObjCSelector(Buffer); Text = method->getObjCSelector().getString(Buffer);
} else if (auto *ctor = dyn_cast<ConstructorDecl>(methodOrCtorOrDtor)) { } else if (auto *ctor = dyn_cast<ConstructorDecl>(methodOrCtorOrDtor)) {
Text = ctor->getObjCSelector(Buffer); Text = ctor->getObjCSelector().getString(Buffer);
} else if (isa<DestructorDecl>(methodOrCtorOrDtor)) { } else if (isa<DestructorDecl>(methodOrCtorOrDtor)) {
Text = "dealloc"; Text = "dealloc";
} else { } else {
@@ -333,11 +333,11 @@ namespace {
} }
Selector(AbstractStorageDecl *asd, ForGetter_t) { Selector(AbstractStorageDecl *asd, ForGetter_t) {
Text = asd->getObjCGetterSelector(Buffer); Text = asd->getObjCGetterSelector().getString(Buffer);
} }
Selector(AbstractStorageDecl *asd, ForSetter_t) { Selector(AbstractStorageDecl *asd, ForSetter_t) {
Text = asd->getObjCSetterSelector(Buffer); Text = asd->getObjCSetterSelector().getString(Buffer);
} }
Selector(SILDeclRef ref) { Selector(SILDeclRef ref) {
@@ -354,11 +354,13 @@ namespace {
break; break;
case SILDeclRef::Kind::Func: case SILDeclRef::Kind::Func:
Text = cast<FuncDecl>(ref.getDecl())->getObjCSelector(Buffer); Text = cast<FuncDecl>(ref.getDecl())->getObjCSelector()
.getString(Buffer);
break; break;
case SILDeclRef::Kind::Initializer: case SILDeclRef::Kind::Initializer:
Text = cast<ConstructorDecl>(ref.getDecl())->getObjCSelector(Buffer); Text = cast<ConstructorDecl>(ref.getDecl())->getObjCSelector()
.getString(Buffer);
break; break;
case SILDeclRef::Kind::IVarInitializer: case SILDeclRef::Kind::IVarInitializer:

View File

@@ -2023,9 +2023,9 @@ void IRGenSILFunction::visitDynamicMethodBranchInst(DynamicMethodBranchInst *i){
StringRef selector; StringRef selector;
llvm::SmallString<64> selectorBuffer; llvm::SmallString<64> selectorBuffer;
if (auto fnDecl = dyn_cast<FuncDecl>(i->getMember().getDecl())) if (auto fnDecl = dyn_cast<FuncDecl>(i->getMember().getDecl()))
selector = fnDecl->getObjCSelector(selectorBuffer); selector = fnDecl->getObjCSelector().getString(selectorBuffer);
else if (auto var = dyn_cast<AbstractStorageDecl>(i->getMember().getDecl())) else if (auto var = dyn_cast<AbstractStorageDecl>(i->getMember().getDecl()))
selector = var->getObjCGetterSelector(selectorBuffer); selector = var->getObjCGetterSelector().getString(selectorBuffer);
else else
llvm_unreachable("Unhandled dynamic method branch query"); llvm_unreachable("Unhandled dynamic method branch query");

View File

@@ -414,7 +414,7 @@ private:
assert(bodyPatterns.size() == 2 && "not an ObjC-compatible method"); assert(bodyPatterns.size() == 2 && "not an ObjC-compatible method");
llvm::SmallString<128> selectorBuf; llvm::SmallString<128> selectorBuf;
StringRef selectorString = AFD->getObjCSelector(selectorBuf); StringRef selectorString = AFD->getObjCSelector().getString(selectorBuf);
if (isa<ParenPattern>(bodyPatterns.back())) { if (isa<ParenPattern>(bodyPatterns.back())) {
// One argument. // One argument.
@@ -493,10 +493,10 @@ private:
if (overridesObjC) { if (overridesObjC) {
llvm::SmallString<64> buffer; llvm::SmallString<64> buffer;
os << ", getter=" << VD->getObjCGetterSelector(buffer); os << ", getter=" << VD->getObjCGetterSelector().getString(buffer);
if (VD->isSettable(nullptr)) { if (VD->isSettable(nullptr)) {
buffer.clear(); buffer.clear();
os << ", setter=" << VD->getObjCSetterSelector(buffer); os << ", setter=" << VD->getObjCSetterSelector().getString(buffer);
} }
} }

View File

@@ -151,7 +151,8 @@ getDynamicResultSignature(ValueDecl *decl,
Type type; Type type;
if (auto func = dyn_cast<FuncDecl>(decl)) { if (auto func = dyn_cast<FuncDecl>(decl)) {
// Handle functions. // Handle functions.
selector = func->getObjCSelector(buffer); // FIXME: Use ObjCSelector here!
selector = func->getObjCSelector().getString(buffer);
type = decl->getType()->castTo<AnyFunctionType>()->getResult(); type = decl->getType()->castTo<AnyFunctionType>()->getResult();
// Append a '+' for static methods, '-' for instance methods. This // Append a '+' for static methods, '-' for instance methods. This
@@ -165,11 +166,11 @@ getDynamicResultSignature(ValueDecl *decl,
selector = buffer.str(); selector = buffer.str();
} else if (auto asd = dyn_cast<AbstractStorageDecl>(decl)) { } else if (auto asd = dyn_cast<AbstractStorageDecl>(decl)) {
// Handle properties and subscripts. Only the getter matters. // Handle properties and subscripts. Only the getter matters.
selector = asd->getObjCGetterSelector(buffer); selector = asd->getObjCGetterSelector().getString(buffer);
type = asd->getType(); type = asd->getType();
} else if (auto ctor = dyn_cast<ConstructorDecl>(decl)) { } else if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
// Handle constructors. // Handle constructors.
selector = ctor->getObjCSelector(buffer); selector = ctor->getObjCSelector().getString(buffer);
type = decl->getType()->castTo<AnyFunctionType>()->getResult(); type = decl->getType()->castTo<AnyFunctionType>()->getResult();
} else { } else {
llvm_unreachable("Dynamic lookup found a non-[objc] result"); llvm_unreachable("Dynamic lookup found a non-[objc] result");

View File

@@ -3273,13 +3273,12 @@ public:
uncurriedDeclTy = uncurriedDeclTy->getUnlabeledType(TC.Context); uncurriedDeclTy = uncurriedDeclTy->getUnlabeledType(TC.Context);
// If the method is an Objective-C method, compute its selector. // If the method is an Objective-C method, compute its selector.
llvm::SmallString<32> methodSelectorBuffer; Optional<ObjCSelector> methodSelector;
StringRef methodSelector;
ObjCSubscriptKind subscriptKind = ObjCSubscriptKind::None; ObjCSubscriptKind subscriptKind = ObjCSubscriptKind::None;
if (decl->isObjC()) { if (decl->isObjC()) {
if (method) if (method)
methodSelector = method->getObjCSelector(methodSelectorBuffer); methodSelector = method->getObjCSelector();
else if (auto *subscript = dyn_cast<SubscriptDecl>(abstractStorage)) else if (auto *subscript = dyn_cast<SubscriptDecl>(abstractStorage))
subscriptKind = subscript->getObjCSubscriptKind(); subscriptKind = subscript->getObjCSubscriptKind();
} }
@@ -3318,8 +3317,7 @@ public:
if (decl->isObjC() && parentDecl->isObjC()) { if (decl->isObjC() && parentDecl->isObjC()) {
if (method) { if (method) {
// If the selectors don't match, it's not an override. // If the selectors don't match, it's not an override.
llvm::SmallString<32> buffer; if (*methodSelector != parentMethod->getObjCSelector())
if (methodSelector != parentMethod->getObjCSelector(buffer))
continue; continue;
objCMatch = true; objCMatch = true;
@@ -3377,7 +3375,7 @@ public:
if (objCMatch) { if (objCMatch) {
if (method) { if (method) {
TC.diagnose(decl, diag::override_objc_type_mismatch_method, TC.diagnose(decl, diag::override_objc_type_mismatch_method,
methodSelector, uncurriedDeclTy); *methodSelector, uncurriedDeclTy);
} else { } else {
TC.diagnose(decl, diag::override_objc_type_mismatch_subscript, TC.diagnose(decl, diag::override_objc_type_mismatch_subscript,
static_cast<unsigned>(subscriptKind), uncurriedDeclTy); static_cast<unsigned>(subscriptKind), uncurriedDeclTy);