@@ -8094,85 +8094,10 @@ bool importer::isViewType(const clang::CXXRecordDecl *decl) {
8094
8094
return !hasOwnedValueAttr (decl) && hasPointerInSubobjects (decl);
8095
8095
}
8096
8096
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).
8164
8097
static 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
-
8170
8098
if (decl->hasSimpleCopyConstructor ())
8171
8099
return true ;
8172
8100
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.
8176
8101
return llvm::any_of (decl->ctors (), [](clang::CXXConstructorDecl *ctor) {
8177
8102
return ctor->isCopyConstructor () && !ctor->isDeleted () &&
8178
8103
!ctor->isIneligibleOrNotSelected () &&
@@ -8183,12 +8108,10 @@ static bool hasCopyTypeOperations(const clang::CXXRecordDecl *decl) {
8183
8108
}
8184
8109
8185
8110
static 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.
8189
8111
if (llvm::any_of (decl->ctors (), [](clang::CXXConstructorDecl *ctor) {
8190
8112
return ctor->isMoveConstructor () &&
8191
- (ctor->isDeleted () || ctor->getAccess () != clang::AS_public);
8113
+ (ctor->isDeleted () || ctor->isIneligibleOrNotSelected () ||
8114
+ ctor->getAccess () != clang::AS_public);
8192
8115
}))
8193
8116
return false ;
8194
8117
@@ -8201,7 +8124,8 @@ static bool hasMoveTypeOperations(const clang::CXXRecordDecl *decl) {
8201
8124
8202
8125
static bool hasDestroyTypeOperations (const clang::CXXRecordDecl *decl) {
8203
8126
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) {
8205
8129
return false ;
8206
8130
}
8207
8131
return true ;
@@ -8257,49 +8181,17 @@ CxxRecordSemantics::evaluate(Evaluator &evaluator,
8257
8181
8258
8182
auto cxxDecl = dyn_cast<clang::CXXRecordDecl>(decl);
8259
8183
if (!cxxDecl) {
8260
- if (hasNonCopyableAttr (decl))
8261
- return CxxRecordSemanticsKind::MoveOnly;
8262
-
8263
- return CxxRecordSemanticsKind::Trivial;
8184
+ return CxxRecordSemanticsKind::Value;
8264
8185
}
8265
8186
8266
8187
if (isSwiftClassType (cxxDecl))
8267
8188
return CxxRecordSemanticsKind::SwiftClassType;
8268
8189
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
-
8286
8190
if (hasIteratorAPIAttr (cxxDecl) || isIterator (cxxDecl)) {
8287
8191
return CxxRecordSemanticsKind::Iterator;
8288
8192
}
8289
8193
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;
8303
8195
}
8304
8196
8305
8197
ValueDecl *
@@ -8330,6 +8222,74 @@ CxxRecordAsSwiftType::evaluate(Evaluator &evaluator,
8330
8222
return nullptr ;
8331
8223
}
8332
8224
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
+
8333
8293
static bool anySubobjectsSelfContained (const clang::CXXRecordDecl *decl) {
8334
8294
// std::pair and std::tuple might have copy and move constructors, or base
8335
8295
// classes with copy and move constructors, but they are not self-contained
0 commit comments