Skip to content

Commit 97a8148

Browse files
authored
[IRGen] Make sure a C++ constructor thunk is called when it's needed (#71790)
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 4154cdb commit 97a8148

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
@@ -3467,6 +3467,10 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded(
34673467
return ctorAddress;
34683468
}
34693469

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

@@ -3547,10 +3551,15 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
35473551
LinkEntity entity =
35483552
LinkEntity::forSILFunction(f, shouldCallPreviousImplementation);
35493553

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

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

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

3586-
clangAddr = emitCXXConstructorThunkIfNeeded(*this, signature, ctor, name,
3595+
clangAddr = emitCXXConstructorThunkIfNeeded(*this, signature, cxxCtor, name,
35873596
clangAddr);
35883597
}
35893598
}

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+
// MICROSOFT_X64: [[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)