Skip to content

Commit f73e20b

Browse files
committed
[cxx-interop] Fix crash when inout parameter is used in some "template contexts".
We used to incorrectly forward inout paramters in the thunk for both template paramters that aren't used in the signature and in the thunk for dependent types as Any. Now this works in the simple case. We'll need to do something more complicated when we have an `inout Any` for dependent types because we will need to somehow cast without copying. This will probably require synthesising the SIL of the thunk manually.
1 parent 4b44ac5 commit f73e20b

File tree

4 files changed

+38
-5
lines changed

4 files changed

+38
-5
lines changed

lib/Sema/CSApply.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,22 @@ synthesizeDependentTypeThunkParamForwarding(AbstractFunctionDecl *afd, void *con
220220
continue;
221221
}
222222

223-
auto paramRefExpr = new (ctx) DeclRefExpr(param, DeclNameLoc(),
224-
/*Implicit=*/true);
223+
Expr *paramRefExpr = new (ctx) DeclRefExpr(param, DeclNameLoc(),
224+
/*Implicit=*/true);
225225
paramRefExpr->setType(param->getType());
226226

227+
if (param->isInOut()) {
228+
paramRefExpr->setType(LValueType::get(param->getType()));
229+
230+
paramRefExpr = new (ctx) InOutExpr(
231+
SourceLoc(), paramRefExpr, param->getType(), /*isImplicit*/ true);
232+
paramRefExpr->setType(InOutType::get(param->getType()));
233+
}
234+
227235
auto specParamTy = specializedFuncDecl->getParameters()->get(paramIndex)->getType();
228236

229237
Expr *argExpr = nullptr;
230-
if (specParamTy->isEqual(paramRefExpr->getType())) {
238+
if (specParamTy->isEqual(param->getType())) {
231239
argExpr = paramRefExpr;
232240
} else {
233241
argExpr = ForcedCheckedCastExpr::createImplicit(ctx, paramRefExpr,
@@ -353,9 +361,18 @@ synthesizeForwardingThunkBody(AbstractFunctionDecl *afd, void *context) {
353361
if (isa<MetatypeType>(param->getType().getPointer())) {
354362
continue;
355363
}
356-
auto paramRefExpr = new (ctx) DeclRefExpr(param, DeclNameLoc(),
357-
/*Implicit=*/true);
364+
Expr *paramRefExpr = new (ctx) DeclRefExpr(param, DeclNameLoc(),
365+
/*Implicit=*/true);
358366
paramRefExpr->setType(param->getType());
367+
368+
if (param->isInOut()) {
369+
paramRefExpr->setType(LValueType::get(param->getType()));
370+
371+
paramRefExpr = new (ctx) InOutExpr(
372+
SourceLoc(), paramRefExpr, param->getType(), /*isImplicit*/ true);
373+
paramRefExpr->setType(InOutType::get(param->getType()));
374+
}
375+
359376
forwardingParams.push_back(Argument(SourceLoc(), Identifier(), paramRefExpr));
360377
}
361378

test/Interop/Cxx/templates/Inputs/template-type-parameter-not-in-signature.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ T templateTypeParamUsedInReturnType(int x) { return x; }
3333
template <typename T>
3434
T templateTypeParamUsedInReferenceParam(T &t) { return t; }
3535

36+
template <typename T, typename U>
37+
T templateTypeParamNotUsedInSignatureWithRef(T &t) { return t; }
38+
3639
template <typename T, typename U>
3740
void templateTypeParamNotUsedInSignatureWithVarargs(...) {}
3841

test/Interop/Cxx/templates/dependent-types.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ DependentTypesTestSuite.test("Multiple dependent arguments (not inferred).") {
3535
expectEqual(m.getValue(), 42)
3636
}
3737

38+
DependentTypesTestSuite.test("Takes inout argument and returns dependent type.") {
39+
var x = 42
40+
let m = refToDependent(&x) as! M<Int>
41+
expectEqual(m.getValue(), 42)
42+
}
43+
44+
3845
// We still have some problems calling methods on Windows: SR-13129 and rdar://88391102
3946
#if !os(Windows)
4047
DependentTypesTestSuite.test("Function template methods") {

test/Interop/Cxx/templates/template-type-parameter-not-in-signature.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,10 @@ TemplateNotInSignatureTestSuite.test("Member function templates (static)") {
3939
Struct.templateTypeParamNotUsedInSignatureStatic(T: Int.self)
4040
}
4141

42+
TemplateNotInSignatureTestSuite.test("Type not used in signature and takes an inout parameter.") {
43+
var x = 42
44+
let out = templateTypeParamNotUsedInSignatureWithRef(&x, U: Int.self)
45+
expectEqual(out, 42)
46+
}
47+
4248
runAllTests()

0 commit comments

Comments
 (0)