@@ -8094,85 +8094,10 @@ bool importer::isViewType(const clang::CXXRecordDecl *decl) {
80948094 return !hasOwnedValueAttr (decl) && hasPointerInSubobjects (decl);
80958095}
80968096
8097- static bool copyConstructorIsDefaulted (const clang::CXXRecordDecl *decl) {
8098- auto ctor = llvm::find_if (decl->ctors (), [](clang::CXXConstructorDecl *ctor) {
8099- return ctor->isCopyConstructor ();
8100- });
8101-
8102- assert (ctor != decl->ctor_end ());
8103- return ctor->isDefaulted ();
8104- }
8105-
8106- static bool copyAssignOperatorIsDefaulted (const clang::CXXRecordDecl *decl) {
8107- auto copyAssignOp = llvm::find_if (decl->decls (), [](clang::Decl *member) {
8108- if (auto method = dyn_cast<clang::CXXMethodDecl>(member))
8109- return method->isCopyAssignmentOperator ();
8110- return false ;
8111- });
8112-
8113- assert (copyAssignOp != decl->decls_end ());
8114- return cast<clang::CXXMethodDecl>(*copyAssignOp)->isDefaulted ();
8115- }
8116-
8117- // / Recursively checks that there are no user-provided copy constructors or
8118- // / destructors in any fields or base classes.
8119- // / Does not check C++ records with specific API annotations.
8120- static bool isSufficientlyTrivial (const clang::CXXRecordDecl *decl) {
8121- // Probably a class template that has not yet been specialized:
8122- if (!decl->getDefinition ())
8123- return true ;
8124-
8125- if ((decl->hasUserDeclaredCopyConstructor () &&
8126- !copyConstructorIsDefaulted (decl)) ||
8127- (decl->hasUserDeclaredCopyAssignment () &&
8128- !copyAssignOperatorIsDefaulted (decl)) ||
8129- (decl->hasUserDeclaredDestructor () && decl->getDestructor () &&
8130- !decl->getDestructor ()->isDefaulted ()))
8131- return false ;
8132-
8133- auto checkType = [](clang::QualType t) {
8134- if (auto recordType = dyn_cast<clang::RecordType>(t.getCanonicalType ())) {
8135- if (auto cxxRecord =
8136- dyn_cast<clang::CXXRecordDecl>(recordType->getDecl ())) {
8137- if (hasImportAsRefAttr (cxxRecord) || hasOwnedValueAttr (cxxRecord) ||
8138- hasUnsafeAPIAttr (cxxRecord))
8139- return true ;
8140-
8141- if (!isSufficientlyTrivial (cxxRecord))
8142- return false ;
8143- }
8144- }
8145-
8146- return true ;
8147- };
8148-
8149- for (auto field : decl->fields ()) {
8150- if (!checkType (field->getType ()))
8151- return false ;
8152- }
8153-
8154- for (auto base : decl->bases ()) {
8155- if (!checkType (base.getType ()))
8156- return false ;
8157- }
8158-
8159- return true ;
8160- }
8161-
8162- // / Checks if a record provides the required value type lifetime operations
8163- // / (copy and destroy).
81648097static bool hasCopyTypeOperations (const clang::CXXRecordDecl *decl) {
8165- // Hack for a base type of std::optional from the Microsoft standard library.
8166- if (decl->isInStdNamespace () && decl->getIdentifier () &&
8167- decl->getName () == " _Optional_construct_base" )
8168- return true ;
8169-
81708098 if (decl->hasSimpleCopyConstructor ())
81718099 return true ;
81728100
8173- // If we have no way of copying the type we can't import the class
8174- // at all because we cannot express the correct semantics as a swift
8175- // struct.
81768101 return llvm::any_of (decl->ctors (), [](clang::CXXConstructorDecl *ctor) {
81778102 return ctor->isCopyConstructor () && !ctor->isDeleted () &&
81788103 !ctor->isIneligibleOrNotSelected () &&
@@ -8183,12 +8108,10 @@ static bool hasCopyTypeOperations(const clang::CXXRecordDecl *decl) {
81838108}
81848109
81858110static bool hasMoveTypeOperations (const clang::CXXRecordDecl *decl) {
8186- // If we have no way of copying the type we can't import the class
8187- // at all because we cannot express the correct semantics as a swift
8188- // struct.
81898111 if (llvm::any_of (decl->ctors (), [](clang::CXXConstructorDecl *ctor) {
81908112 return ctor->isMoveConstructor () &&
8191- (ctor->isDeleted () || ctor->getAccess () != clang::AS_public);
8113+ (ctor->isDeleted () || ctor->isIneligibleOrNotSelected () ||
8114+ ctor->getAccess () != clang::AS_public);
81928115 }))
81938116 return false ;
81948117
@@ -8201,7 +8124,8 @@ static bool hasMoveTypeOperations(const clang::CXXRecordDecl *decl) {
82018124
82028125static bool hasDestroyTypeOperations (const clang::CXXRecordDecl *decl) {
82038126 if (auto dtor = decl->getDestructor ()) {
8204- if (dtor->isDeleted () || dtor->getAccess () != clang::AS_public) {
8127+ if (dtor->isDeleted () || dtor->isIneligibleOrNotSelected () ||
8128+ dtor->getAccess () != clang::AS_public) {
82058129 return false ;
82068130 }
82078131 return true ;
@@ -8257,49 +8181,17 @@ CxxRecordSemantics::evaluate(Evaluator &evaluator,
82578181
82588182 auto cxxDecl = dyn_cast<clang::CXXRecordDecl>(decl);
82598183 if (!cxxDecl) {
8260- if (hasNonCopyableAttr (decl))
8261- return CxxRecordSemanticsKind::MoveOnly;
8262-
8263- return CxxRecordSemanticsKind::Trivial;
8184+ return CxxRecordSemanticsKind::Value;
82648185 }
82658186
82668187 if (isSwiftClassType (cxxDecl))
82678188 return CxxRecordSemanticsKind::SwiftClassType;
82688189
8269- if (!hasDestroyTypeOperations (cxxDecl) ||
8270- (!hasCopyTypeOperations (cxxDecl) && !hasMoveTypeOperations (cxxDecl))) {
8271-
8272- if (hasConstructorWithUnsupportedDefaultArgs (cxxDecl))
8273- return CxxRecordSemanticsKind::UnavailableConstructors;
8274-
8275- return CxxRecordSemanticsKind::MissingLifetimeOperation;
8276- }
8277-
8278- if (hasNonCopyableAttr (cxxDecl) && hasMoveTypeOperations (cxxDecl)) {
8279- return CxxRecordSemanticsKind::MoveOnly;
8280- }
8281-
8282- if (hasOwnedValueAttr (cxxDecl)) {
8283- return CxxRecordSemanticsKind::Owned;
8284- }
8285-
82868190 if (hasIteratorAPIAttr (cxxDecl) || isIterator (cxxDecl)) {
82878191 return CxxRecordSemanticsKind::Iterator;
82888192 }
82898193
8290- if (hasCopyTypeOperations (cxxDecl)) {
8291- return CxxRecordSemanticsKind::Owned;
8292- }
8293-
8294- if (hasMoveTypeOperations (cxxDecl)) {
8295- return CxxRecordSemanticsKind::MoveOnly;
8296- }
8297-
8298- if (isSufficientlyTrivial (cxxDecl)) {
8299- return CxxRecordSemanticsKind::Trivial;
8300- }
8301-
8302- llvm_unreachable (" Could not classify C++ type." );
8194+ return CxxRecordSemanticsKind::Value;
83038195}
83048196
83058197ValueDecl *
@@ -8330,6 +8222,74 @@ CxxRecordAsSwiftType::evaluate(Evaluator &evaluator,
83308222 return nullptr ;
83318223}
83328224
8225+ CxxValueSemanticsKind
8226+ CxxValueSemantics::evaluate (Evaluator &evaluator,
8227+ CxxValueSemanticsDescriptor desc) const {
8228+
8229+ const auto *type = desc.type ;
8230+
8231+ auto desugared = type->getUnqualifiedDesugaredType ();
8232+ const auto *recordType = desugared->getAs <clang::RecordType>();
8233+ if (!recordType)
8234+ return CxxValueSemanticsKind::Copyable;
8235+
8236+ auto recordDecl = recordType->getDecl ();
8237+
8238+ // When a reference type is copied, the pointer’s value is copied rather than
8239+ // the object’s storage. This means reference types can be imported as
8240+ // copyable to Swift, even when they are non-copyable in C++.
8241+ if (recordHasReferenceSemantics (recordDecl, desc.importerImpl ))
8242+ return CxxValueSemanticsKind::Copyable;
8243+
8244+ if (recordDecl->isInStdNamespace ()) {
8245+ // Hack for a base type of std::optional from the Microsoft standard
8246+ // library.
8247+ if (recordDecl->getIdentifier () &&
8248+ recordDecl->getName () == " _Optional_construct_base" )
8249+ return CxxValueSemanticsKind::Copyable;
8250+ }
8251+
8252+ const auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(recordDecl);
8253+ if (!cxxRecordDecl) {
8254+ if (hasNonCopyableAttr (recordDecl))
8255+ return CxxValueSemanticsKind::MoveOnly;
8256+ return CxxValueSemanticsKind::Copyable;
8257+ }
8258+
8259+ bool isCopyable = hasCopyTypeOperations (cxxRecordDecl);
8260+ bool isMovable = hasMoveTypeOperations (cxxRecordDecl);
8261+
8262+ if (!hasDestroyTypeOperations (cxxRecordDecl) || (!isCopyable && !isMovable)) {
8263+
8264+ if (hasConstructorWithUnsupportedDefaultArgs (cxxRecordDecl))
8265+ return CxxValueSemanticsKind::UnavailableConstructors;
8266+
8267+ return CxxValueSemanticsKind::MissingLifetimeOperation;
8268+ }
8269+
8270+ if (hasNonCopyableAttr (cxxRecordDecl) && isMovable)
8271+ return CxxValueSemanticsKind::MoveOnly;
8272+
8273+ if (isCopyable)
8274+ return CxxValueSemanticsKind::Copyable;
8275+
8276+ if (isMovable)
8277+ return CxxValueSemanticsKind::MoveOnly;
8278+
8279+ llvm_unreachable (" Could not classify C++ type." );
8280+ }
8281+
8282+ void swift::simple_display (llvm::raw_ostream &out,
8283+ CxxValueSemanticsDescriptor desc) {
8284+ out << " Checking if '" ;
8285+ out << clang::QualType (desc.type , 0 ).getAsString ();
8286+ out << " ' is copyable or movable." ;
8287+ }
8288+
8289+ SourceLoc swift::extractNearestSourceLoc (CxxValueSemanticsDescriptor) {
8290+ return SourceLoc ();
8291+ }
8292+
83338293static bool anySubobjectsSelfContained (const clang::CXXRecordDecl *decl) {
83348294 // std::pair and std::tuple might have copy and move constructors, or base
83358295 // classes with copy and move constructors, but they are not self-contained
0 commit comments