Skip to content

Commit d3770b3

Browse files
committed
[cxx-interop] Make sure to create empty initializers for C++ structs
The existing synthesis mechanism had a bug: `cxxRecordDecl->hasDefaultConstructor()` returns true for C++ types with an implicit default constructor, for instance, `pthread_mutexattr_t`. rdar://113708880
1 parent f02ca3b commit d3770b3

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,18 +2381,30 @@ namespace {
23812381
hasMemberwiseInitializer = false;
23822382
}
23832383

2384-
if (hasZeroInitializableStorage &&
2385-
!(cxxRecordDecl && cxxRecordDecl->hasDefaultConstructor())) {
2386-
// Add default constructor for the struct if compiling in C mode.
2387-
// If we're compiling for C++:
2388-
// 1. If a default constructor is declared, don't synthesize one.
2389-
// 2. If a default constructor is deleted, don't try to synthesize one.
2390-
// 3. If there is no default constructor, synthesize a C-like default
2391-
// constructor that zero-initializes the backing memory of the
2392-
// struct. This is important to maintain source compatibility when a
2393-
// client enables C++ interop in an existing project that uses C
2394-
// interop and might rely on the fact that C structs have a default
2395-
// constructor available in Swift.
2384+
// Add default constructor for the struct if compiling in C mode.
2385+
// If we're compiling for C++:
2386+
// 1. If a default constructor is declared, don't synthesize one.
2387+
// 2. If a default constructor is deleted, don't try to synthesize one.
2388+
// 3. If there is no default constructor, synthesize a C-like default
2389+
// constructor that zero-initializes the backing memory of the
2390+
// struct. This is important to maintain source compatibility when a
2391+
// client enables C++ interop in an existing project that uses C
2392+
// interop and might rely on the fact that C structs have a default
2393+
// constructor available in Swift.
2394+
bool needsEmptyInitializer = true;
2395+
if (cxxRecordDecl) {
2396+
if (auto structResult = dyn_cast<StructDecl>(result)) {
2397+
for (auto member : structResult->getMembers()) {
2398+
if (auto constructorDecl = dyn_cast<ConstructorDecl>(member)) {
2399+
if (constructorDecl->getParameters()->size() == 0) {
2400+
needsEmptyInitializer = false;
2401+
break;
2402+
}
2403+
}
2404+
}
2405+
}
2406+
}
2407+
if (hasZeroInitializableStorage && needsEmptyInitializer) {
23962408
ConstructorDecl *defaultCtor =
23972409
synthesizer.createDefaultConstructor(result);
23982410
ctors.push_back(defaultCtor);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -enable-objc-interop -enable-experimental-cxx-interop
2+
// REQUIRES: OS=macosx
3+
4+
import Darwin
5+
6+
_ = pthread_mutexattr_t() // expected-warning {{'init()' is deprecated: This zero-initializes the backing memory of the struct}}

0 commit comments

Comments
 (0)