Skip to content

Commit 9de4cf8

Browse files
committed
[cxx-interop] Synthesize subscript without requiring ClangNode
This scenario happens when a derived class inherits operator[] from a base class. The derived class's operator[] is a synthesized shim, which (currently) does not have a ClangNode associated with it. This prevents an assertion failure in SubscriptDecl::createImported(). rdar://167701851
1 parent 88a449b commit 9de4cf8

File tree

4 files changed

+19
-7
lines changed

4 files changed

+19
-7
lines changed

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,10 +1899,19 @@ SubscriptDecl *SwiftDeclSynthesizer::makeSubscript(FuncDecl *getter,
18991899
DeclName name(ctx, DeclBaseName::createSubscript(), bodyParams);
19001900
auto dc = getterImpl->getDeclContext();
19011901

1902-
SubscriptDecl *subscript = SubscriptDecl::createImported(
1903-
ctx, name, getterImpl->getLoc(), bodyParams, getterImpl->getLoc(),
1904-
elementTy, dc, getterImpl->getGenericParams(),
1905-
getterImpl->getClangNode());
1902+
SubscriptDecl *subscript;
1903+
if (auto ClangN = getterImpl->getClangNode()) {
1904+
subscript = SubscriptDecl::createImported(
1905+
ctx, name, getterImpl->getLoc(), bodyParams, getterImpl->getLoc(),
1906+
elementTy, dc, getterImpl->getGenericParams(), ClangN);
1907+
} else {
1908+
// getterImpl may lack an associated ClangNode if it is synthesized,
1909+
// e.g., if it is a cloned from a base class member due to inheritance.
1910+
subscript = SubscriptDecl::create(
1911+
ctx, name, SourceLoc(), StaticSpellingKind::None, getterImpl->getLoc(),
1912+
bodyParams, getterImpl->getLoc(), elementTy, dc,
1913+
getterImpl->getGenericParams());
1914+
}
19061915
subscript->copyFormalAccessFrom(getterImpl);
19071916

19081917
bool useAddress = rawElementTy->getAnyPointerElementType() &&

test/Interop/Cxx/class/inheritance/Inputs/using-base-members.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@ struct OperatorBase {
6868
operator bool() const { return true; }
6969
int operator*() const { return 456; }
7070
OperatorBase operator!() const { return *this; }
71-
// int operator[](const int x) const { return x; } // FIXME: see below
71+
int operator[](const int x) const { return x; }
7272
};
7373

7474
struct OperatorBasePrivateInheritance : private OperatorBase {
7575
public:
7676
using OperatorBase::operator bool;
7777
using OperatorBase::operator*;
7878
using OperatorBase::operator!;
79-
// using OperatorBase::operator[]; // FIXME: using operator[] is broken
79+
using OperatorBase::operator[];
8080
};
8181

8282
#endif // !_USING_BASE_MEMBERS_H

test/Interop/Cxx/class/inheritance/using-base-members-executable.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ UsingBaseTestSuite.test("OperatorBasePrivateInheritance") {
6060
// expectTrue(Bool(fromCxx: p))
6161
// expectTrue(Bool(fromCxx: !p))
6262
expectEqual(456, p.pointee)
63-
// expectEqual(789, p[789]) // FIXME: operator[] is currently broken
63+
expectEqual(789, p[789])
6464
}
6565

6666
runAllTests()

test/Interop/Cxx/class/inheritance/using-base-members-module-interface.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,14 @@
7070

7171
// CHECK: public struct OperatorBasePrivateInheritance : CxxConvertibleToBool {
7272
// CHECK-NEXT: public init()
73+
// CHECK-NEXT: public subscript(x: Int32) -> Int32 { get }
7374
// CHECK-NEXT: public var pointee: Int32 { get }
7475
// CHECK-NEXT: public func __convertToBool() -> Bool
7576
// CHECK-NEXT: @available(*, unavailable, message: "use .pointee property")
7677
// CHECK-NEXT: public func __operatorStar() -> Int32
7778
// CHECK-NEXT: prefix public static func ! (lhs: OperatorBasePrivateInheritance) -> OperatorBase
7879
// CHECK-NEXT: @available(*, unavailable, message: "use ! instead")
7980
// CHECK-NEXT: public func __operatorExclaim() -> OperatorBase
81+
// CHECK-NEXT: @available(*, unavailable, message: "use subscript")
82+
// CHECK-NEXT: public func __operatorSubscriptConst(_ x: Int32) -> Int32
8083
// CHECK-NEXT: }

0 commit comments

Comments
 (0)