Skip to content

[cxx-interop] Emit IR for virtual methods #61828

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/IRGen/GenClangDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ void IRGenModule::emitClangDecl(const clang::Decl *decl) {
}
}

// If something from a C++ class is used, emit all virtual methods of this
// class because they might be emitted in the vtable even if not used
// directly from Swift.
if (auto *record = dyn_cast<clang::CXXRecordDecl>(next->getDeclContext())) {
for (auto *method : record->methods()) {
if (method->isVirtual()) {
callback(method);
}
}
}

if (auto var = dyn_cast<clang::VarDecl>(next))
if (!var->isFileVarDecl())
continue;
Expand Down
5 changes: 5 additions & 0 deletions test/Interop/Cxx/class/inheritance/Inputs/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ module SubTypes {
module TypeAliases {
header "type-aliases.h"
}

module VirtualMethods {
header "virtual-methods.h"
requires cplusplus
}
29 changes: 29 additions & 0 deletions test/Interop/Cxx/class/inheritance/Inputs/virtual-methods.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
extern "C" void puts(const char *);

inline void testFunctionCollected() {
puts("test\n");
}

struct Base {
virtual void foo() = 0;
};

template <class T>
struct Derived : Base {
inline void foo() override {
testFunctionCollected();
}

void callMe() {
}
};

using DerivedInt = Derived<int>;

template <class T>
struct Unused : Base {
inline void foo() override {
}
};

using UnusedInt = Unused<int>;
17 changes: 17 additions & 0 deletions test/Interop/Cxx/class/inheritance/virtual-methods-irgen.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %target-swift-emit-ir -I %S/Inputs -enable-experimental-cxx-interop %s -validate-tbd-against-ir=none | %FileCheck %s

// FIXME: enable on Windows
// XFAIL: OS=windows-msvc

import VirtualMethods

var x = DerivedInt()
x.callMe()

// CHECK: define {{.*}}void @{{_ZN7DerivedIiE3fooEv|"\?foo@\?$Derived@H@@UEAAXXZ"}}
// CHECK: call void @{{_Z21testFunctionCollectedv|"\?testFunctionCollected@@YAXXZ"}}

// CHECK: define {{.*}}void @{{_Z21testFunctionCollectedv|"\?testFunctionCollected@@YAXXZ"}}

// CHECK-NOT: _ZN6UnusedIiE3fooEv
// CHECK-NOT: "\?foo@\?$Unused@H@@UEAAXXZ"