Skip to content

Commit fe88a00

Browse files
authored
[interop][SwiftToCxx] Skip emitting an accessor method if its name collides with an accessor method of another property
Resolves rdar://119835520 and rdar://119835571.
1 parent 5637284 commit fe88a00

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

lib/PrintAsClang/DeclAndTypePrinter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ namespace clang {
2626

2727
namespace swift {
2828

29+
class AccessorDecl;
2930
class PrimitiveTypeMapping;
3031
class ValueDecl;
3132
class SwiftToClangInteropContext;
@@ -41,6 +42,7 @@ struct CxxDeclEmissionScope {
4142
/// lexical scope.
4243
llvm::StringMap<llvm::SmallVector<const AbstractFunctionDecl *, 2>>
4344
emittedFunctionOverloads;
45+
llvm::StringMap<const AccessorDecl *> emittedAccessorMethodNames;
4446
};
4547

4648
/// Responsible for printing a Swift Decl or Type in Objective-C, to be

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1476,6 +1476,27 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
14761476
}
14771477
}
14781478

1479+
static bool checkDuplicatedMethodName(StringRef funcName,
1480+
const AccessorDecl *AD,
1481+
DeclAndTypePrinter &declAndTypePrinter,
1482+
raw_ostream &os) {
1483+
auto *&decl = declAndTypePrinter.getCxxDeclEmissionScope()
1484+
.emittedAccessorMethodNames[funcName];
1485+
1486+
if (!decl) {
1487+
// This is the first time an accessor with this name has been emitted.
1488+
decl = AD;
1489+
} else if (decl != AD) {
1490+
// An accessor for another property had the same name.
1491+
os << " // skip emitting accessor method for \'"
1492+
<< AD->getStorage()->getBaseIdentifier().str() << "\'. \'" << funcName
1493+
<< "\' already declared.\n";
1494+
return false;
1495+
}
1496+
1497+
return true;
1498+
}
1499+
14791500
void DeclAndTypeClangFunctionPrinter::printCxxMethod(
14801501
DeclAndTypePrinter &declAndTypePrinter,
14811502
const NominalTypeDecl *typeDeclContext, const AbstractFunctionDecl *FD,
@@ -1552,6 +1573,12 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
15521573
Type resultTy, bool isStatic, bool isDefinition,
15531574
std::optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo) {
15541575
assert(accessor->isSetter() || accessor->getParameters()->size() == 0);
1576+
std::string accessorName = remapPropertyName(accessor, resultTy);
1577+
1578+
if (!checkDuplicatedMethodName(accessorName, accessor, declAndTypePrinter,
1579+
os))
1580+
return;
1581+
15551582
os << " ";
15561583

15571584
FunctionSignatureModifiers modifiers;
@@ -1563,9 +1590,9 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
15631590
!isStatic && accessor->isGetter() && !isa<ClassDecl>(typeDeclContext);
15641591
modifiers.hasSymbolUSR = !isDefinition;
15651592
modifiers.symbolUSROverride = accessor->getStorage();
1566-
auto result = printFunctionSignature(
1567-
accessor, signature, remapPropertyName(accessor, resultTy), resultTy,
1568-
FunctionSignatureKind::CxxInlineThunk, modifiers);
1593+
auto result =
1594+
printFunctionSignature(accessor, signature, accessorName, resultTy,
1595+
FunctionSignatureKind::CxxInlineThunk, modifiers);
15691596
assert(!result.isUnsupported() && "C signature should be unsupported too!");
15701597
declAndTypePrinter.printAvailability(os, accessor->getStorage());
15711598
if (!isDefinition) {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %s -typecheck -clang-header-expose-decls=all-public -emit-clang-header-path %t/name-collision.h
3+
// RUN: %FileCheck %s < %t/name-collision.h
4+
5+
public class C0 {
6+
public static var description: String { "hello" }
7+
public var description: String { "world" }
8+
}
9+
10+
public class C1 {
11+
public var feat: Int { 123 }
12+
public var Feat: Int { 123 }
13+
}
14+
15+
// CHECK: class SWIFT_SYMBOL("s:4main2C0C") C0 :
16+
// CHECK-NOT: getDescription()
17+
// CHECK: static SWIFT_INLINE_THUNK swift::String getDescription()
18+
// CHECK: skip emitting accessor method for 'description'. 'getDescription' already declared.
19+
// CHECK-NOT: getDescription()
20+
// CHECK:};
21+
22+
// CHECK: class SWIFT_SYMBOL("s:4main2C1C") C1 :
23+
// CHECK-NOT: getFeat()
24+
// CHECK: SWIFT_INLINE_THUNK swift::Int getFeat()
25+
// CHECK: skip emitting accessor method for 'Feat'. 'getFeat' already declared.
26+
// CHECK-NOT: getFeat()
27+
// CHECK:};
28+
29+
// CHECK: namespace main SWIFT_PRIVATE_ATTR SWIFT_SYMBOL_MODULE("main") {
30+
// CHECK-NOT: getDescription()
31+
// CHECK: SWIFT_INLINE_THUNK swift::String C0::getDescription() {
32+
// CHECK: skip emitting accessor method for 'description'. 'getDescription' already declared.
33+
// CHECK-NOT: getDescription()
34+
// CHECK-NOT: getFeat()
35+
// CHECK: SWIFT_INLINE_THUNK swift::Int C1::getFeat() {
36+
// CHECK: skip emitting accessor method for 'Feat'. 'getFeat' already declared.
37+
// CHECK-NOT: getFeat()

0 commit comments

Comments
 (0)