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