Skip to content

Commit 29961e0

Browse files
committed
[IRGen] Make sure a C++ constructor thunk is called when it's needed
This fixes a bug where the thunk for a C++ constructor call wasn't being called when the constructor was called the second time.
1 parent d3d4bd2 commit 29961e0

File tree

3 files changed

+19
-8
lines changed

3 files changed

+19
-8
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3466,6 +3466,10 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded(
34663466
return ctorAddress;
34673467
}
34683468

3469+
// Check whether we've created the thunk already.
3470+
if (auto *thunkFn = IGM.Module.getFunction(name))
3471+
return thunkFn;
3472+
34693473
llvm::Function *thunk = llvm::Function::Create(
34703474
assumedFnType, llvm::Function::PrivateLinkage, name, &IGM.Module);
34713475

@@ -3546,10 +3550,15 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
35463550
LinkEntity entity =
35473551
LinkEntity::forSILFunction(f, shouldCallPreviousImplementation);
35483552

3549-
// Check whether we've created the function already.
3553+
auto clangDecl = f->getClangDecl();
3554+
auto cxxCtor = dyn_cast_or_null<clang::CXXConstructorDecl>(clangDecl);
3555+
3556+
// Check whether we've created the function already. If the function is a C++
3557+
// constructor, don't return the constructor here as a thunk might be needed
3558+
// to call the constructor.
35503559
// FIXME: We should integrate this into the LinkEntity cache more cleanly.
35513560
llvm::Function *fn = Module.getFunction(entity.mangleAsString());
3552-
if (fn) {
3561+
if (fn && !cxxCtor) {
35533562
if (forDefinition) {
35543563
updateLinkageForDefinition(*this, fn, entity);
35553564
}
@@ -3561,7 +3570,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
35613570
// the insert-before point.
35623571
llvm::Constant *clangAddr = nullptr;
35633572
bool isObjCDirect = false;
3564-
if (auto clangDecl = f->getClangDecl()) {
3573+
if (clangDecl) {
35653574
// If we have an Objective-C Clang declaration, it must be a direct
35663575
// method and we want to generate the IR declaration ourselves.
35673576
if (auto objcDecl = dyn_cast<clang::ObjCMethodDecl>(clangDecl)) {
@@ -3572,7 +3581,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
35723581
clangAddr = getAddrOfClangGlobalDecl(globalDecl, forDefinition);
35733582
}
35743583

3575-
if (auto ctor = dyn_cast<clang::CXXConstructorDecl>(clangDecl)) {
3584+
if (cxxCtor) {
35763585
Signature signature = getSignature(f->getLoweredFunctionType());
35773586

35783587
// The thunk has private linkage, so it doesn't need to have a predictable
@@ -3582,7 +3591,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
35823591
stream << "__swift_cxx_ctor";
35833592
entity.mangle(stream);
35843593

3585-
clangAddr = emitCXXConstructorThunkIfNeeded(*this, signature, ctor, name,
3594+
clangAddr = emitCXXConstructorThunkIfNeeded(*this, signature, cxxCtor, name,
35863595
clangAddr);
35873596
}
35883597
}

test/Interop/Cxx/class/constructors-irgen-windows.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ import Constructors
99
import TypeClassification
1010

1111
public func createHasVirtualBase() -> HasVirtualBase {
12-
// MICROSOFT_X64: define dllexport swiftcc void @"$s7MySwift20createHasVirtualBaseSo0{{bcD0VyF|deF0VyF}}"(ptr noalias sret({{.*}}) %0)
12+
// MICROSOFT_X64: define dllexport swiftcc void @"$s7MySwift20createHasVirtualBaseSo0{{bcD0VyF|deF0VyF}}"(ptr noalias sret({{.*}}) [[V0:%.*]])
1313
// MICROSOFT_X64-NOT: define
1414
// Note `this` return type and implicit "most derived" argument.
15-
// MICROSOFT_X64: call ptr @"??0HasVirtualBase@@QEAA@UArgType@@@Z"(ptr %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 1)
15+
// [[V1:%.*]] = alloca %{{.*}}, align 8
16+
// MICROSOFT_X64: call ptr @"??0HasVirtualBase@@QEAA@UArgType@@@Z"(ptr [[V1]], i32 %{{[0-9]+}}, i32 1)
17+
// MICROSOFT_X64: call ptr @"??0HasVirtualBase@@QEAA@UArgType@@@Z"(ptr [[V0]], i32 %{{[0-9]+}}, i32 1)
18+
let _ : HasVirtualBase = HasVirtualBase(ArgType())
1619
return HasVirtualBase(ArgType())
1720
}
1821

test/Interop/Cxx/value-witness-table/custom-destructors-virtual.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -Xcc -fno-rtti -O)
77
//
88
// REQUIRES: executable_test
9-
// XFAIL: OS=windows-msvc
109

1110
import CustomDestructor
1211
import StdlibUnittest

0 commit comments

Comments
 (0)