@@ -3476,7 +3476,12 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded(
34763476 llvm::FunctionType *ctorFnType =
34773477 cast<llvm::FunctionType>(clangFunc->getValueType ());
34783478
3479- if (assumedFnType == ctorFnType) {
3479+ // Only need a thunk if either:
3480+ // 1. The calling conventions do not match, and we need to pass arguments
3481+ // differently.
3482+ // 2. This is a default constructor, and we need to zero the backing memory of
3483+ // the struct.
3484+ if (assumedFnType == ctorFnType && !ctor->isDefaultConstructor ()) {
34803485 return ctorAddress;
34813486 }
34823487
@@ -3510,14 +3515,34 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded(
35103515 Args.push_back (i);
35113516 }
35123517
3513- clang::CodeGen::ImplicitCXXConstructorArgs implicitArgs =
3514- clang::CodeGen::getImplicitCXXConstructorArgs (IGM.ClangCodeGen ->CGM (),
3515- ctor);
3516- for (size_t i = 0 ; i < implicitArgs.Prefix .size (); ++i) {
3517- Args.insert (Args.begin () + 1 + i, implicitArgs.Prefix [i]);
3518+ if (assumedFnType != ctorFnType) {
3519+ clang::CodeGen::ImplicitCXXConstructorArgs implicitArgs =
3520+ clang::CodeGen::getImplicitCXXConstructorArgs (IGM.ClangCodeGen ->CGM (),
3521+ ctor);
3522+ for (size_t i = 0 ; i < implicitArgs.Prefix .size (); ++i) {
3523+ Args.insert (Args.begin () + 1 + i, implicitArgs.Prefix [i]);
3524+ }
3525+ for (const auto &arg : implicitArgs.Suffix ) {
3526+ Args.push_back (arg);
3527+ }
35183528 }
3519- for (const auto &arg : implicitArgs.Suffix ) {
3520- Args.push_back (arg);
3529+
3530+ if (ctor->isDefaultConstructor ()) {
3531+ assert (Args.size () > 0 && " expected at least 1 argument (result address) "
3532+ " for default constructor" );
3533+
3534+ // Zero out the backing memory of the struct.
3535+ // This makes default initializers for C++ structs behave consistently with
3536+ // the synthesized empty initializers for C structs. When C++ interop is
3537+ // enabled in a project, all imported C structs are treated as C++ structs,
3538+ // which sometimes means that Clang will synthesize a default constructor
3539+ // for the C++ struct that does not zero out trivial fields of a struct.
3540+ auto cxxRecord = ctor->getParent ();
3541+ clang::ASTContext &ctx = cxxRecord->getASTContext ();
3542+ auto typeSize = ctx.getTypeSizeInChars (ctx.getRecordType (cxxRecord));
3543+ subIGF.Builder .CreateMemSet (Args[0 ],
3544+ llvm::ConstantInt::get (subIGF.IGM .Int8Ty , 0 ),
3545+ typeSize.getQuantity (), llvm::MaybeAlign ());
35213546 }
35223547
35233548 auto *call =
0 commit comments