Skip to content

Commit 2e447dc

Browse files
authored
NameTranslation: ensure that preferred names are preferred to implicit names in @objc(). rdar://30658589 (#7692)
Implicit names in @objc() are essentially cached auto-translated Swift names. This patch ensures that we don't mistake them for explicitly specified objc selectors.
1 parent 4c92bf4 commit 2e447dc

File tree

2 files changed

+33
-12
lines changed

2 files changed

+33
-12
lines changed

lib/AST/Decl.cpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3375,14 +3375,31 @@ void AbstractStorageDecl::setInvalidBracesRange(SourceRange BracesRange) {
33753375
GetSetInfo.setPointer(getSetInfo);
33763376
}
33773377

3378+
static Optional<ObjCSelector>
3379+
getNameFromObjcAttribute(const ObjCAttr *attr, DeclName preferredName) {
3380+
if (!attr)
3381+
return None;
3382+
if (auto name = attr->getName()) {
3383+
if (attr->isNameImplicit()) {
3384+
// preferredName > implicit name, because implicit name is just cached
3385+
// actual name.
3386+
if (!preferredName)
3387+
return *name;
3388+
} else {
3389+
// explicit name > preferred name.
3390+
return *name;
3391+
}
3392+
}
3393+
return None;
3394+
}
3395+
33783396
ObjCSelector AbstractStorageDecl::getObjCGetterSelector(
33793397
LazyResolver *resolver, Identifier preferredName) const {
33803398
// If the getter has an @objc attribute with a name, use that.
33813399
if (auto getter = getGetter()) {
3382-
if (auto objcAttr = getter->getAttrs().getAttribute<ObjCAttr>()) {
3383-
if (auto name = objcAttr->getName())
3400+
if (auto name = getNameFromObjcAttribute(getter->getAttrs().
3401+
getAttribute<ObjCAttr>(), preferredName))
33843402
return *name;
3385-
}
33863403
}
33873404

33883405
// Subscripts use a specific selector.
@@ -3414,9 +3431,8 @@ ObjCSelector AbstractStorageDecl::getObjCSetterSelector(
34143431
auto setter = getSetter();
34153432
auto objcAttr = setter ? setter->getAttrs().getAttribute<ObjCAttr>()
34163433
: nullptr;
3417-
if (objcAttr) {
3418-
if (auto name = objcAttr->getName())
3419-
return *name;
3434+
if (auto name = getNameFromObjcAttribute(objcAttr, DeclName(preferredName))) {
3435+
return *name;
34203436
}
34213437

34223438
// Subscripts use a specific selector.
@@ -3445,7 +3461,7 @@ ObjCSelector AbstractStorageDecl::getObjCSetterSelector(
34453461
auto result = VarDecl::getDefaultObjCSetterSelector(ctx, Name);
34463462

34473463
// Cache the result, so we don't perform string manipulation again.
3448-
if (objcAttr)
3464+
if (objcAttr && preferredName.empty())
34493465
const_cast<ObjCAttr *>(objcAttr)->setName(result, /*implicit=*/true);
34503466

34513467
return result;
@@ -4228,10 +4244,9 @@ SourceRange AbstractFunctionDecl::getSignatureSourceRange() const {
42284244
ObjCSelector AbstractFunctionDecl::getObjCSelector(
42294245
LazyResolver *resolver, DeclName preferredName) const {
42304246
// If there is an @objc attribute with a name, use that name.
4231-
auto objc = getAttrs().getAttribute<ObjCAttr>();
4232-
if (objc) {
4233-
if (auto name = objc->getName())
4234-
return *name;
4247+
auto *objc = getAttrs().getAttribute<ObjCAttr>();
4248+
if (auto name = getNameFromObjcAttribute(objc, preferredName)) {
4249+
return *name;
42354250
}
42364251

42374252
auto &ctx = getASTContext();
@@ -4357,7 +4372,7 @@ ObjCSelector AbstractFunctionDecl::getObjCSelector(
43574372

43584373
// If we did any string manipulation, cache the result. We don't want to
43594374
// do that again.
4360-
if (didStringManipulation && objc)
4375+
if (didStringManipulation && objc && !preferredName)
43614376
const_cast<ObjCAttr *>(objc)->setName(result, /*implicit=*/true);
43624377

43634378
return result;

test/SourceKit/NameTranslation/swiftnames.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ func takeError(_ e : CustomError) {
4747
@objc(C2ObjC)
4848
class C2 {}
4949

50+
@objc open class /*MyClass*/MyClass: NSObject {
51+
@objc open func /*MyClass_foo*/foo(/*MyClass_foo_p1*/bar: Int, /*MyClass_foo_p2*/baz: Int) {}
52+
}
53+
5054
// REQUIRES: objc_interop
5155
// RUN: %sourcekitd-test -req=translate -swift-name "foo(a:b:c:)" -pos=11:11 %s -- -F %S/Inputs/mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK1 %s
5256
// RUN: %sourcekitd-test -req=translate -swift-name "foo(a1:b1:c1:)" -pos=11:11 %s -- -F %S/Inputs/mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK2 %s
@@ -68,6 +72,7 @@ class C2 {}
6872
// RUN: %sourcekitd-test -req=translate -swift-name "a2" -pos=41:10 %s -- -F %S/Inputs/mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK14 %s
6973
// RUN: %sourcekitd-test -req=translate -swift-name "A2" -pos=41:10 %s -- -F %S/Inputs/mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK14 %s
7074
// RUN: %sourcekitd-test -req=translate -swift-name "C3" -pos=48:8 %s -- -F %S/Inputs/mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK15 %s
75+
// RUN: %sourcekitd-test -req=translate -swift-name "bar(_:other:)" -pos=51:36 %s -- -F %S/Inputs/mock-sdk -I %t.tmp %mcp_opt %s | %FileCheck -check-prefix=CHECK16 %s
7176

7277
// CHECK-NONE: <empty name translation info>
7378
// CHECK1: fooWithA:b:c:
@@ -86,3 +91,4 @@ class C2 {}
8691
// CHECK13: CommonFixA2
8792
// CHECK14: CustomErrorA2
8893
// CHECK15: C2ObjC
94+
// CHECK16: bar:other:

0 commit comments

Comments
 (0)