@@ -2381,32 +2381,6 @@ namespace {
2381
2381
hasMemberwiseInitializer = false ;
2382
2382
}
2383
2383
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.
2396
- ConstructorDecl *defaultCtor =
2397
- synthesizer.createDefaultConstructor (result);
2398
- ctors.push_back (defaultCtor);
2399
- if (cxxRecordDecl) {
2400
- auto attr = AvailableAttr::createPlatformAgnostic (
2401
- defaultCtor->getASTContext (),
2402
- " This zero-initializes the backing memory of the struct, which "
2403
- " is unsafe for some C++ structs. Consider adding an explicit "
2404
- " default initializer for this C++ struct." ,
2405
- " " , PlatformAgnosticAvailabilityKind::Deprecated);
2406
- defaultCtor->getAttrs ().add (attr);
2407
- }
2408
- }
2409
-
2410
2384
bool forceMemberwiseInitializer = false ;
2411
2385
if (cxxRecordDecl && cxxRecordDecl->isInStdNamespace () &&
2412
2386
cxxRecordDecl->getIdentifier () &&
@@ -2447,6 +2421,44 @@ namespace {
2447
2421
}
2448
2422
}
2449
2423
2424
+ // Add default constructor for the struct if compiling in C mode.
2425
+ // If we're compiling for C++:
2426
+ // 1. If a default constructor is declared, don't synthesize one.
2427
+ // 2. If a default constructor is deleted, don't try to synthesize one.
2428
+ // 3. If there is no default constructor, synthesize a C-like default
2429
+ // constructor that zero-initializes the backing memory of the
2430
+ // struct. This is important to maintain source compatibility when a
2431
+ // client enables C++ interop in an existing project that uses C
2432
+ // interop and might rely on the fact that C structs have a default
2433
+ // constructor available in Swift.
2434
+ bool needsEmptyInitializer = true ;
2435
+ if (cxxRecordDecl) {
2436
+ if (auto structResult = dyn_cast<StructDecl>(result)) {
2437
+ for (auto member : structResult->getMembers ()) {
2438
+ if (auto constructorDecl = dyn_cast<ConstructorDecl>(member)) {
2439
+ if (constructorDecl->getParameters ()->size () == 0 ) {
2440
+ needsEmptyInitializer = false ;
2441
+ break ;
2442
+ }
2443
+ }
2444
+ }
2445
+ }
2446
+ }
2447
+ if (hasZeroInitializableStorage && needsEmptyInitializer) {
2448
+ ConstructorDecl *defaultCtor =
2449
+ synthesizer.createDefaultConstructor (result);
2450
+ ctors.push_back (defaultCtor);
2451
+ if (cxxRecordDecl) {
2452
+ auto attr = AvailableAttr::createPlatformAgnostic (
2453
+ defaultCtor->getASTContext (),
2454
+ " This zero-initializes the backing memory of the struct, which "
2455
+ " is unsafe for some C++ structs. Consider adding an explicit "
2456
+ " default initializer for this C++ struct." ,
2457
+ " " , PlatformAgnosticAvailabilityKind::Deprecated);
2458
+ defaultCtor->getAttrs ().add (attr);
2459
+ }
2460
+ }
2461
+
2450
2462
if (auto structResult = dyn_cast<StructDecl>(result)) {
2451
2463
structResult->setHasUnreferenceableStorage (hasUnreferenceableStorage);
2452
2464
if (isNonTrivialPtrAuth) {
0 commit comments