@@ -3461,7 +3461,12 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded(
34613461 llvm::FunctionType *ctorFnType =
34623462 cast<llvm::FunctionType>(clangFunc->getValueType ());
34633463
3464- if (assumedFnType == ctorFnType) {
3464+ // Only need a thunk if either:
3465+ // 1. The calling conventions do not match, and we need to pass arguments
3466+ // differently.
3467+ // 2. This is a default constructor, and we need to zero the backing memory of
3468+ // the struct.
3469+ if (assumedFnType == ctorFnType && !ctor->isDefaultConstructor ()) {
34653470 return ctorAddress;
34663471 }
34673472
@@ -3495,14 +3500,34 @@ llvm::Constant *swift::irgen::emitCXXConstructorThunkIfNeeded(
34953500 Args.push_back (i);
34963501 }
34973502
3498- clang::CodeGen::ImplicitCXXConstructorArgs implicitArgs =
3499- clang::CodeGen::getImplicitCXXConstructorArgs (IGM.ClangCodeGen ->CGM (),
3500- ctor);
3501- for (size_t i = 0 ; i < implicitArgs.Prefix .size (); ++i) {
3502- Args.insert (Args.begin () + 1 + i, implicitArgs.Prefix [i]);
3503+ if (assumedFnType != ctorFnType) {
3504+ clang::CodeGen::ImplicitCXXConstructorArgs implicitArgs =
3505+ clang::CodeGen::getImplicitCXXConstructorArgs (IGM.ClangCodeGen ->CGM (),
3506+ ctor);
3507+ for (size_t i = 0 ; i < implicitArgs.Prefix .size (); ++i) {
3508+ Args.insert (Args.begin () + 1 + i, implicitArgs.Prefix [i]);
3509+ }
3510+ for (const auto &arg : implicitArgs.Suffix ) {
3511+ Args.push_back (arg);
3512+ }
35033513 }
3504- for (const auto &arg : implicitArgs.Suffix ) {
3505- Args.push_back (arg);
3514+
3515+ if (ctor->isDefaultConstructor ()) {
3516+ assert (Args.size () > 0 && " expected at least 1 argument (result address) "
3517+ " for default constructor" );
3518+
3519+ // Zero out the backing memory of the struct.
3520+ // This makes default initializers for C++ structs behave consistently with
3521+ // the synthesized empty initializers for C structs. When C++ interop is
3522+ // enabled in a project, all imported C structs are treated as C++ structs,
3523+ // which sometimes means that Clang will synthesize a default constructor
3524+ // for the C++ struct that does not zero out trivial fields of a struct.
3525+ auto cxxRecord = ctor->getParent ();
3526+ clang::ASTContext &ctx = cxxRecord->getASTContext ();
3527+ auto typeSize = ctx.getTypeSizeInChars (ctx.getRecordType (cxxRecord));
3528+ subIGF.Builder .CreateMemSet (Args[0 ],
3529+ llvm::ConstantInt::get (subIGF.IGM .Int8Ty , 0 ),
3530+ typeSize.getQuantity (), llvm::MaybeAlign ());
35063531 }
35073532
35083533 auto *call =
0 commit comments