@@ -2447,9 +2447,39 @@ namespace {
2447
2447
}
2448
2448
2449
2449
if (cxxRecordDecl) {
2450
+ // FIXME: Swift right now uses AddressOnly type layout
2451
+ // in a way that conflates C++ types
2452
+ // that need to be destroyed or copied explicitly with C++
2453
+ // types that have to be passed indirectly, because
2454
+ // only AddressOnly types can be copied or destroyed using C++
2455
+ // semantics. However, in actuality these two concepts are
2456
+ // separate and don't map to one notion of AddressOnly type
2457
+ // layout cleanly. We should reserve the use of AddressOnly
2458
+ // type layout when types have to use C++ copy/move/destroy
2459
+ // operations, but allow AddressOnly types to be passed
2460
+ // directly as well. This will help unify the MSVC and
2461
+ // Itanium difference here, and will allow us to support
2462
+ // trivial_abi C++ types as well.
2463
+ auto isNonTrivialForPurposeOfCalls =
2464
+ [](const clang::CXXRecordDecl *decl) -> bool {
2465
+ return decl->hasNonTrivialCopyConstructor () ||
2466
+ decl->hasNonTrivialMoveConstructor () ||
2467
+ !decl->hasTrivialDestructor ();
2468
+ };
2469
+ auto isAddressOnlySwiftStruct =
2470
+ [&](const clang::CXXRecordDecl *decl) -> bool {
2471
+ // MSVC ABI allows non-trivially destroyed C++ types
2472
+ // to be passed in register. This is not supported, as such
2473
+ // type wouldn't be destroyed in Swift correctly. Therefore,
2474
+ // force AddressOnly type layout using the old heuristic.
2475
+ // FIXME: Support can pass in registers for MSVC correctly.
2476
+ if (Impl.SwiftContext .LangOpts .Target .isWindowsMSVCEnvironment ())
2477
+ return isNonTrivialForPurposeOfCalls (decl);
2478
+ return !decl->canPassInRegisters ();
2479
+ };
2450
2480
if (auto structResult = dyn_cast<StructDecl>(result))
2451
2481
structResult->setIsCxxNonTrivial (
2452
- !cxxRecordDecl-> canPassInRegisters ( ));
2482
+ isAddressOnlySwiftStruct (cxxRecordDecl ));
2453
2483
2454
2484
for (auto &getterAndSetter : Impl.GetterSetterMap [result]) {
2455
2485
auto getter = getterAndSetter.second .first ;
0 commit comments