@@ -2472,39 +2472,33 @@ namespace {
24722472 }
24732473
24742474 if (cxxRecordDecl) {
2475- // FIXME: Swift right now uses AddressOnly type layout
2476- // in a way that conflates C++ types
2477- // that need to be destroyed or copied explicitly with C++
2478- // types that have to be passed indirectly, because
2479- // only AddressOnly types can be copied or destroyed using C++
2480- // semantics. However, in actuality these two concepts are
2481- // separate and don't map to one notion of AddressOnly type
2482- // layout cleanly. We should reserve the use of AddressOnly
2483- // type layout when types have to use C++ copy/move/destroy
2484- // operations, but allow AddressOnly types to be passed
2485- // directly as well. This will help unify the MSVC and
2486- // Itanium difference here, and will allow us to support
2487- // trivial_abi C++ types as well.
2488- auto isNonTrivialForPurposeOfCalls =
2489- [](const clang::CXXRecordDecl *decl) -> bool {
2490- return decl->hasNonTrivialCopyConstructor () ||
2491- decl->hasNonTrivialMoveConstructor () ||
2492- !decl->hasTrivialDestructor ();
2493- };
2494- auto isAddressOnlySwiftStruct =
2495- [&](const clang::CXXRecordDecl *decl) -> bool {
2496- // MSVC ABI allows non-trivially destroyed C++ types
2497- // to be passed in register. This is not supported, as such
2498- // type wouldn't be destroyed in Swift correctly. Therefore,
2499- // force AddressOnly type layout using the old heuristic.
2500- // FIXME: Support can pass in registers for MSVC correctly.
2501- if (Impl.SwiftContext .LangOpts .Target .isWindowsMSVCEnvironment ())
2502- return isNonTrivialForPurposeOfCalls (decl);
2503- return !decl->canPassInRegisters ();
2504- };
2505- if (auto structResult = dyn_cast<StructDecl>(result))
2506- structResult->setIsCxxNonTrivial (
2507- isAddressOnlySwiftStruct (cxxRecordDecl));
2475+ if (auto structResult = dyn_cast<StructDecl>(result)) {
2476+ // Address-only type is a type that can't be passed in registers.
2477+ // Address-only types are typically non-trivial, however some
2478+ // non-trivial types can be loadable as well (although such types
2479+ // are not yet available in Swift).
2480+ bool isAddressOnly = !cxxRecordDecl->canPassInRegisters ();
2481+ // Check if the given type is non-trivial to ensure we can
2482+ // still perform the right copy/move/destroy even if it's
2483+ // not an address-only type.
2484+ auto isNonTrivial = [](const clang::CXXRecordDecl *decl) -> bool {
2485+ return decl->hasNonTrivialCopyConstructor () ||
2486+ decl->hasNonTrivialMoveConstructor () ||
2487+ !decl->hasTrivialDestructor ();
2488+ };
2489+ if (!isAddressOnly &&
2490+ Impl.SwiftContext .LangOpts .Target .isWindowsMSVCEnvironment () &&
2491+ isNonTrivial (cxxRecordDecl)) {
2492+ // MSVC ABI allows non-trivially destroyed C++ types
2493+ // to be passed in register. This is not supported, as such
2494+ // type wouldn't be destroyed in Swift correctly. Therefore,
2495+ // mark this type as unavailable.
2496+ // FIXME: Support can pass in registers for MSVC correctly.
2497+ Impl.markUnavailable (result, " non-trivial C++ class with trivial "
2498+ " ABI is not yet available in Swift" );
2499+ }
2500+ structResult->setIsCxxNonTrivial (isAddressOnly);
2501+ }
25082502
25092503 for (auto &getterAndSetter : Impl.GetterSetterMap [result]) {
25102504 auto getter = getterAndSetter.second .first ;
0 commit comments