diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 7663b5dabf04a..c3c0f08346217 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -3466,6 +3466,10 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded( return ctorAddress; } + // Check whether we've created the thunk already. + if (auto *thunkFn = IGM.Module.getFunction(name)) + return thunkFn; + llvm::Function *thunk = llvm::Function::Create( assumedFnType, llvm::Function::PrivateLinkage, name, &IGM.Module); @@ -3546,10 +3550,15 @@ llvm::Function *IRGenModule::getAddrOfSILFunction( LinkEntity entity = LinkEntity::forSILFunction(f, shouldCallPreviousImplementation); - // Check whether we've created the function already. + auto clangDecl = f->getClangDecl(); + auto cxxCtor = dyn_cast_or_null(clangDecl); + + // Check whether we've created the function already. If the function is a C++ + // constructor, don't return the constructor here as a thunk might be needed + // to call the constructor. // FIXME: We should integrate this into the LinkEntity cache more cleanly. llvm::Function *fn = Module.getFunction(entity.mangleAsString()); - if (fn) { + if (fn && !cxxCtor) { if (forDefinition) { updateLinkageForDefinition(*this, fn, entity); } @@ -3561,7 +3570,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction( // the insert-before point. llvm::Constant *clangAddr = nullptr; bool isObjCDirect = false; - if (auto clangDecl = f->getClangDecl()) { + if (clangDecl) { // If we have an Objective-C Clang declaration, it must be a direct // method and we want to generate the IR declaration ourselves. if (auto objcDecl = dyn_cast(clangDecl)) { @@ -3572,7 +3581,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction( clangAddr = getAddrOfClangGlobalDecl(globalDecl, forDefinition); } - if (auto ctor = dyn_cast(clangDecl)) { + if (cxxCtor) { Signature signature = getSignature(f->getLoweredFunctionType()); // The thunk has private linkage, so it doesn't need to have a predictable @@ -3582,7 +3591,7 @@ llvm::Function *IRGenModule::getAddrOfSILFunction( stream << "__swift_cxx_ctor"; entity.mangle(stream); - clangAddr = emitCXXConstructorThunkIfNeeded(*this, signature, ctor, name, + clangAddr = emitCXXConstructorThunkIfNeeded(*this, signature, cxxCtor, name, clangAddr); } } diff --git a/test/Interop/Cxx/class/constructors-irgen-windows.swift b/test/Interop/Cxx/class/constructors-irgen-windows.swift index 9d9c274b65187..4239aedce8ad6 100644 --- a/test/Interop/Cxx/class/constructors-irgen-windows.swift +++ b/test/Interop/Cxx/class/constructors-irgen-windows.swift @@ -9,10 +9,13 @@ import Constructors import TypeClassification public func createHasVirtualBase() -> HasVirtualBase { - // MICROSOFT_X64: define dllexport swiftcc void @"$s7MySwift20createHasVirtualBaseSo0{{bcD0VyF|deF0VyF}}"(ptr noalias sret({{.*}}) %0) + // MICROSOFT_X64: define dllexport swiftcc void @"$s7MySwift20createHasVirtualBaseSo0{{bcD0VyF|deF0VyF}}"(ptr noalias sret({{.*}}) [[V0:%.*]]) // MICROSOFT_X64-NOT: define // Note `this` return type and implicit "most derived" argument. - // MICROSOFT_X64: call ptr @"??0HasVirtualBase@@QEAA@UArgType@@@Z"(ptr %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 1) + // MICROSOFT_X64: [[V1:%.*]] = alloca %{{.*}}, align 8 + // MICROSOFT_X64: call ptr @"??0HasVirtualBase@@QEAA@UArgType@@@Z"(ptr [[V1]], i32 %{{[0-9]+}}, i32 1) + // MICROSOFT_X64: call ptr @"??0HasVirtualBase@@QEAA@UArgType@@@Z"(ptr [[V0]], i32 %{{[0-9]+}}, i32 1) + let _ : HasVirtualBase = HasVirtualBase(ArgType()) return HasVirtualBase(ArgType()) } diff --git a/test/Interop/Cxx/value-witness-table/custom-destructors-virtual.swift b/test/Interop/Cxx/value-witness-table/custom-destructors-virtual.swift index cb92fb50735f4..8ec9bd748fe92 100644 --- a/test/Interop/Cxx/value-witness-table/custom-destructors-virtual.swift +++ b/test/Interop/Cxx/value-witness-table/custom-destructors-virtual.swift @@ -6,7 +6,6 @@ // RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop -Xcc -fno-rtti -O) // // REQUIRES: executable_test -// XFAIL: OS=windows-msvc import CustomDestructor import StdlibUnittest