Skip to content

Commit cfa10f6

Browse files
committed
[cxx-interop] Do not crash when calling a subscript with unnamed parameter
This fixes a crash in SILGen when calling a C++ subscript that has an unnamed parameter from Swift. The parameters from a C++ `operator[]` get carried over to the synthesized Swift subscript. If the Swift parameter has no name, there is no way to refer to it in SIL. However, the synthesized subscript accessor needs to pass this parameter to C++. This change makes sure that we give a name to the Swift parameter if there isn't already a name on the C++ side. rdar://83163841 (cherry picked from commit ae27e88)
1 parent 092d01c commit cfa10f6

File tree

5 files changed

+52
-1
lines changed

5 files changed

+52
-1
lines changed

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1692,7 +1692,16 @@ SubscriptDecl *SwiftDeclSynthesizer::makeSubscript(FuncDecl *getter,
16921692
: rawElementTy;
16931693

16941694
auto &ctx = ImporterImpl.SwiftContext;
1695-
auto bodyParams = getterImpl->getParameters();
1695+
1696+
assert(getterImpl->getParameters()->size() == 1 &&
1697+
"subscript can only have 1 parameter");
1698+
auto bodyParam = ParamDecl::clone(ctx, getterImpl->getParameters()->get(0));
1699+
// If the subscript parameter is unnamed, give it a name to make sure SILGen
1700+
// creates a variable for it.
1701+
if (bodyParam->getName().empty())
1702+
bodyParam->setName(ctx.getIdentifier("__index"));
1703+
1704+
auto bodyParams = ParameterList::create(ctx, bodyParam);
16961705
DeclName name(ctx, DeclBaseName::createSubscript(), bodyParams);
16971706
auto dc = getterImpl->getDeclContext();
16981707

test/Interop/Cxx/operators/Inputs/member-inline.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,16 @@ struct DerivedFromReadWriteIntArray : ReadWriteIntArray {};
386386

387387
struct DerivedFromNonTrivialArrayByVal : NonTrivialArrayByVal {};
388388

389+
struct SubscriptUnnamedParameter {
390+
int operator[](int) const { return 123; }
391+
};
392+
393+
struct SubscriptUnnamedParameterReadWrite {
394+
int value = 0;
395+
const int &operator[](int) const { return value; }
396+
int &operator[](int) { return value; }
397+
};
398+
389399
struct Iterator {
390400
private:
391401
int value = 123;

test/Interop/Cxx/operators/member-inline-module-interface.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,13 @@
210210
// CHECK: mutating func __operatorSubscriptConst(_ x: Int32) -> NonTrivial
211211
// CHECK: }
212212

213+
// CHECK: struct SubscriptUnnamedParameter {
214+
// CHECK: subscript(__index: Int32) -> Int32 { get }
215+
// CHECK: }
216+
// CHECK: struct SubscriptUnnamedParameterReadWrite {
217+
// CHECK: subscript(__index: Int32) -> Int32
218+
// CHECK: }
219+
213220
// CHECK: struct Iterator {
214221
// CHECK: var pointee: Int32 { mutating get set }
215222
// CHECK: @available(*, unavailable, message: "use .pointee property")

test/Interop/Cxx/operators/member-inline-silgen.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,15 @@ public func index(_ arr: inout ConstPtrByVal, _ arg: Int32, _ val: Int32) -> Int
171171
// CHECK: end_access [[SELFACCESS]] : $*ConstPtrByVal
172172
// CHECK: } // end sil function '$sSo13ConstPtrByValVySPys5Int32VGSgADcig
173173

174+
public func subscriptUnnamed(_ unnamed: SubscriptUnnamedParameter, _ arg: Int32) -> Int32 { unnamed[arg] }
175+
// CHECK: sil shared [transparent] @$sSo25SubscriptUnnamedParameterVys5Int32VADcig : $@convention(method) (Int32, SubscriptUnnamedParameter) -> Int32 {
176+
// CHECK: bb0([[INDEX:%.*]] : $Int32, [[SELF:%.*]] : $SubscriptUnnamedParameter):
177+
// CHECK: [[SELFACCESS:%.*]] = alloc_stack $SubscriptUnnamedParameter
178+
// CHECK: [[OP:%.*]] = function_ref [[OPERATORNAME:@(_ZNK25SubscriptUnnamedParameterixEi|\?\?ASubscriptUnnamedParameter@@QEBAHH@Z)]] : $@convention(cxx_method) (Int32, @in_guaranteed SubscriptUnnamedParameter) -> Int32
179+
// CHECK: [[PTR:%.*]] = apply [[OP]]([[INDEX]], [[SELFACCESS]]) : $@convention(cxx_method) (Int32, @in_guaranteed SubscriptUnnamedParameter) -> Int32
180+
// CHECK: dealloc_stack [[SELFACCESS]]
181+
// CHECK: } // end sil function '$sSo25SubscriptUnnamedParameterVys5Int32VADcig'
182+
174183
// CHECK: sil [clang ReadOnlyIntArray.__operatorSubscriptConst] [[READCLASSNAME]] : $@convention(cxx_method) (Int32, @in_guaranteed ReadOnlyIntArray) -> UnsafePointer<Int32>
175184
// CHECK: sil [clang ReadWriteIntArray.__operatorSubscript] [[READWRITECLASSNAME]] : $@convention(cxx_method) (Int32, @inout ReadWriteIntArray) -> UnsafeMutablePointer<Int32>
176185
// CHECK: sil [clang NonTrivialIntArrayByVal.__operatorSubscriptConst] [[READWRITECLASSNAMEBYVAL]] : $@convention(cxx_method) (Int32, @in_guaranteed NonTrivialIntArrayByVal) -> Int32

test/Interop/Cxx/operators/member-inline.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,22 @@ OperatorsTestSuite.test("SubscriptSetterConst") {
393393
setterConst[0] = 10
394394
}
395395

396+
OperatorsTestSuite.test("SubscriptUnnamedParameter") {
397+
let unnamed = SubscriptUnnamedParameter()
398+
expectEqual(123, unnamed[0])
399+
expectEqual(123, unnamed[321])
400+
}
401+
402+
OperatorsTestSuite.test("SubscriptUnnamedParameterReadWrite") {
403+
var unnamed = SubscriptUnnamedParameterReadWrite()
404+
expectEqual(0, unnamed[0])
405+
expectEqual(0, unnamed[321])
406+
407+
unnamed[456] = 456
408+
expectEqual(456, unnamed[0])
409+
expectEqual(456, unnamed[321])
410+
}
411+
396412
OperatorsTestSuite.test("DerivedFromConstIteratorPrivatelyWithUsingDecl.pointee") {
397413
let stars = DerivedFromConstIteratorPrivatelyWithUsingDecl()
398414
let res = stars.pointee

0 commit comments

Comments
 (0)