Skip to content

Commit 6ca60b0

Browse files
committed
[cxx-interop] Emit IR for virtual methods
Even if a virtual method is not used directly from Swift, it might get emitted into the vtable, and in that case the IR for it should be emitted to avoid linker errors. Fixes #61730.
1 parent 89c032c commit 6ca60b0

File tree

4 files changed

+62
-0
lines changed

4 files changed

+62
-0
lines changed

lib/IRGen/GenClangDecl.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,17 @@ void IRGenModule::emitClangDecl(const clang::Decl *decl) {
201201
}
202202
}
203203

204+
// If something from a C++ class is used, emit all virtual methods of this
205+
// class because they might be emitted in the vtable even if not used
206+
// directly from Swift.
207+
if (auto *record = dyn_cast<clang::CXXRecordDecl>(next->getDeclContext())) {
208+
for (auto *method : record->methods()) {
209+
if (method->isVirtual()) {
210+
callback(method);
211+
}
212+
}
213+
}
214+
204215
if (auto var = dyn_cast<clang::VarDecl>(next))
205216
if (!var->isFileVarDecl())
206217
continue;

test/Interop/Cxx/class/inheritance/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,8 @@ module SubTypes {
1313
module TypeAliases {
1414
header "type-aliases.h"
1515
}
16+
17+
module VirtualMethods {
18+
header "virtual-methods.h"
19+
requires cplusplus
20+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
extern "C" void puts(const char *);
2+
3+
inline void testFunctionCollected() {
4+
puts("test\n");
5+
}
6+
7+
struct Base {
8+
virtual void foo() = 0;
9+
};
10+
11+
template <class T>
12+
struct Derived : Base {
13+
inline void foo() override {
14+
testFunctionCollected();
15+
}
16+
17+
void callMe() {
18+
}
19+
};
20+
21+
using DerivedInt = Derived<int>;
22+
23+
template <class T>
24+
struct Unused : Base {
25+
inline void foo() override {
26+
}
27+
};
28+
29+
using UnusedInt = Unused<int>;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-emit-ir -I %S/Inputs -enable-experimental-cxx-interop %s -validate-tbd-against-ir=none | %FileCheck %s
2+
3+
// FIXME: enable on Windows
4+
// XFAIL: OS=windows-msvc
5+
6+
import VirtualMethods
7+
8+
var x = DerivedInt()
9+
x.callMe()
10+
11+
// CHECK: define {{.*}}void @{{_ZN7DerivedIiE3fooEv|"\?foo@\?$Derived@H@@UEAAXXZ"}}
12+
// CHECK: call void @{{_Z21testFunctionCollectedv|"\?testFunctionCollected@@YAXXZ"}}
13+
14+
// CHECK: define {{.*}}void @{{_Z21testFunctionCollectedv|"\?testFunctionCollected@@YAXXZ"}}
15+
16+
// CHECK-NOT: _ZN6UnusedIiE3fooEv
17+
// CHECK-NOT: "\?foo@\?$Unused@H@@UEAAXXZ"

0 commit comments

Comments
 (0)