Skip to content

Commit 981ad66

Browse files
authored
Merge pull request #85711 from Xazax-hun/virtual-move-only-types
[cxx-interop] Fix crash when virtual methods take move-only types
2 parents e9eff08 + c473c55 commit 981ad66

File tree

4 files changed

+47
-3
lines changed

4 files changed

+47
-3
lines changed

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,12 +2259,21 @@ clang::CXXMethodDecl *SwiftDeclSynthesizer::synthesizeCXXForwardingMethod(
22592259
clang::Expr *argExpr = new (clangCtx) clang::DeclRefExpr(
22602260
clangCtx, param, false, type.getNonReferenceType(),
22612261
clang::ExprValueKind::VK_LValue, clang::SourceLocation());
2262-
if (type->isRValueReferenceType()) {
2262+
bool isMoveOnly = false;
2263+
if (!type->isReferenceType())
2264+
if (evaluateOrDefault(
2265+
ImporterImpl.SwiftContext.evaluator,
2266+
CxxValueSemantics({type.getTypePtr(), &ImporterImpl}),
2267+
{}) == CxxValueSemanticsKind::MoveOnly)
2268+
isMoveOnly = true;
2269+
if (type->isRValueReferenceType() || isMoveOnly) {
22632270
argExpr = clangSema
22642271
.BuildCXXNamedCast(
22652272
clang::SourceLocation(), clang::tok::kw_static_cast,
2266-
clangCtx.getTrivialTypeSourceInfo(type), argExpr,
2267-
clang::SourceRange(), clang::SourceRange())
2273+
clangCtx.getTrivialTypeSourceInfo(
2274+
isMoveOnly ? clangCtx.getRValueReferenceType(type)
2275+
: type),
2276+
argExpr, clang::SourceRange(), clang::SourceRange())
22682277
.get();
22692278
}
22702279
args.push_back(argExpr);

test/Interop/Cxx/foreign-reference/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ module VirtMethodWithRvalRef {
8383
requires cplusplus
8484
}
8585

86+
module VirtMethodWitMoveOnly {
87+
header "virtual-methods-move-only-type.h"
88+
requires cplusplus
89+
}
90+
8691
module LoggingFrts {
8792
header "logging-frts.h"
8893
requires cplusplus
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#include "swift/bridging"
4+
5+
struct MoveOnly {
6+
MoveOnly() {}
7+
MoveOnly(MoveOnly&&) {}
8+
MoveOnly(const MoveOnly&) = delete;
9+
~MoveOnly() {}
10+
};
11+
12+
class CxxForeignRef;
13+
14+
void retain(CxxForeignRef * obj);
15+
void release(CxxForeignRef * obj);
16+
17+
class CxxForeignRef {
18+
public:
19+
CxxForeignRef(const CxxForeignRef &) = delete;
20+
CxxForeignRef() = default;
21+
22+
virtual void takesMoveOnly(MoveOnly);
23+
} SWIFT_SHARED_REFERENCE(retain, release);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %target-swift-frontend -typecheck -verify -I %S/Inputs -I %swift_src_root/lib/ClangImporter/SwiftBridging %s -cxx-interoperability-mode=default -disable-availability-checking
2+
3+
import VirtMethodWitMoveOnly
4+
5+
func f(_ x: CxxForeignRef, _ y: consuming MoveOnly) {
6+
x.takesMoveOnly(y)
7+
}

0 commit comments

Comments
 (0)