Skip to content

Commit 0877933

Browse files
author
Gabor Horvath
committed
[cxx-interop] Fix import virtual methods with rvalue ref params
We generate forwarding calls for virutal methods. These forwarding calls had a type error when the original parameter had an rvalue reference type. In those scenarios we need to insert a static cast to make the type checker happy. rdar://154969620
1 parent a47d392 commit 0877933

File tree

4 files changed

+46
-5
lines changed

4 files changed

+46
-5
lines changed

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,11 +2176,18 @@ clang::CXXMethodDecl *SwiftDeclSynthesizer::synthesizeCXXForwardingMethod(
21762176
for (size_t i = 0; i < newMethod->getNumParams(); ++i) {
21772177
auto *param = newMethod->getParamDecl(i);
21782178
auto type = param->getType();
2179-
if (type->isReferenceType())
2180-
type = type->getPointeeType();
2181-
args.push_back(new (clangCtx) clang::DeclRefExpr(
2182-
clangCtx, param, false, type, clang::ExprValueKind::VK_LValue,
2183-
clang::SourceLocation()));
2179+
clang::Expr *argExpr = new (clangCtx) clang::DeclRefExpr(
2180+
clangCtx, param, false, type.getNonReferenceType(),
2181+
clang::ExprValueKind::VK_LValue, clang::SourceLocation());
2182+
if (type->isRValueReferenceType()) {
2183+
argExpr = clangSema
2184+
.BuildCXXNamedCast(
2185+
clang::SourceLocation(), clang::tok::kw_static_cast,
2186+
clangCtx.getTrivialTypeSourceInfo(type), argExpr,
2187+
clang::SourceRange(), clang::SourceRange())
2188+
.get();
2189+
}
2190+
args.push_back(argExpr);
21842191
}
21852192
auto memberCall = clangSema.BuildCallExpr(
21862193
nullptr, memberExpr, clang::SourceLocation(), args,

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,8 @@ module Printed {
6767
header "printed.h"
6868
requires cplusplus
6969
}
70+
71+
module VirtMethodWithRvalRef {
72+
header "virtual-methods-with-rvalue-reference.h"
73+
requires cplusplus
74+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include "swift/bridging"
4+
5+
class CxxForeignRef;
6+
7+
void retain(CxxForeignRef * obj);
8+
void release(CxxForeignRef * obj);
9+
10+
struct NonTrivial {
11+
NonTrivial(const NonTrivial &other);
12+
~NonTrivial();
13+
};
14+
15+
class CxxForeignRef {
16+
public:
17+
CxxForeignRef(const CxxForeignRef &) = delete;
18+
CxxForeignRef() = default;
19+
20+
virtual void takesRValRef(NonTrivial &&);
21+
} SWIFT_SHARED_REFERENCE(retain, release);
22+
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 VirtMethodWithRvalRef
4+
5+
func f(_ x: CxxForeignRef, _ y: NonTrivial) {
6+
x.takesRValRef(consuming: y)
7+
}

0 commit comments

Comments
 (0)