@@ -1960,10 +1960,21 @@ namespace {
19601960 !Impl.SwiftContext .LangOpts .CForeignReferenceTypes )
19611961 return false ;
19621962
1963+ return decl->hasAttrs () && llvm::any_of (decl->getAttrs (), [](auto *attr) {
1964+ if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
1965+ return swiftAttr->getAttribute () == " import_reference" ||
1966+ // TODO: Remove this once libSwift hosttools no longer
1967+ // requires it.
1968+ swiftAttr->getAttribute () == " import_as_ref" ;
1969+ return false ;
1970+ });
1971+ }
1972+
1973+ bool recordHasMoveOnlySemantics (const clang::RecordDecl *decl) {
19631974 auto semanticsKind = evaluateOrDefault (
19641975 Impl.SwiftContext .evaluator ,
19651976 CxxRecordSemantics ({decl, Impl.SwiftContext }), {});
1966- return semanticsKind == CxxRecordSemanticsKind::Reference ;
1977+ return semanticsKind == CxxRecordSemanticsKind::MoveOnly ;
19671978 }
19681979
19691980 Decl *VisitRecordDecl (const clang::RecordDecl *decl) {
@@ -2118,6 +2129,20 @@ namespace {
21182129 decl, AccessLevel::Public, loc, name, loc, None, nullptr , dc);
21192130 Impl.ImportedDecls [{decl->getCanonicalDecl (), getVersion ()}] = result;
21202131
2132+ if (recordHasMoveOnlySemantics (decl)) {
2133+ if (!Impl.SwiftContext .LangOpts .hasFeature (Feature::MoveOnly)) {
2134+ Impl.addImportDiagnostic (
2135+ decl, Diagnostic (
2136+ diag::move_only_requires_move_only,
2137+ Impl.SwiftContext .AllocateCopy (decl->getNameAsString ())),
2138+ decl->getLocation ());
2139+ return nullptr ;
2140+ }
2141+
2142+ result->getAttrs ().add (new (Impl.SwiftContext )
2143+ MoveOnlyAttr (/* Implicit=*/ true ));
2144+ }
2145+
21212146 // FIXME: Figure out what to do with superclasses in C++. One possible
21222147 // solution would be to turn them into members and add conversion
21232148 // functions.
@@ -2573,33 +2598,42 @@ namespace {
25732598 // default). Make sure we only do this if the class has been fully defined
25742599 // and we're not in a dependent context (this is equivalent to the logic
25752600 // in CanDeclareSpecialMemberFunction in Clang's SemaLookup.cpp).
2576- if (decl-> getDefinition () && !decl-> isBeingDefined () &&
2577- !decl->isDependentContext ()) {
2601+ // TODO: I suspect this if-statement does not need to be here.
2602+ if (!decl-> isBeingDefined () && !decl->isDependentContext ()) {
25782603 if (decl->needsImplicitDefaultConstructor ()) {
25792604 clang::CXXConstructorDecl *ctor =
25802605 clangSema.DeclareImplicitDefaultConstructor (
2581- const_cast <clang::CXXRecordDecl *>(decl-> getDefinition () ));
2606+ const_cast <clang::CXXRecordDecl *>(decl));
25822607 if (!ctor->isDeleted ())
25832608 clangSema.DefineImplicitDefaultConstructor (clang::SourceLocation (),
25842609 ctor);
25852610 }
25862611 clang::CXXConstructorDecl *copyCtor = nullptr ;
2612+ clang::CXXConstructorDecl *moveCtor = nullptr ;
25872613 if (decl->needsImplicitCopyConstructor ()) {
25882614 copyCtor = clangSema.DeclareImplicitCopyConstructor (
25892615 const_cast <clang::CXXRecordDecl *>(decl));
2616+ } else if (decl->needsImplicitMoveConstructor ()) {
2617+ moveCtor = clangSema.DeclareImplicitMoveConstructor (
2618+ const_cast <clang::CXXRecordDecl *>(decl));
25902619 } else {
25912620 // We may have a defaulted copy constructor that needs to be defined.
25922621 // Try to find it.
25932622 for (auto methods : decl->methods ()) {
25942623 if (auto declCtor = dyn_cast<clang::CXXConstructorDecl>(methods)) {
2595- if (declCtor->isCopyConstructor () && declCtor-> isDefaulted () &&
2624+ if (declCtor->isDefaulted () &&
25962625 declCtor->getAccess () == clang::AS_public &&
25972626 !declCtor->isDeleted () &&
25982627 // Note: we use "doesThisDeclarationHaveABody" here because
25992628 // that's what "DefineImplicitCopyConstructor" checks.
26002629 !declCtor->doesThisDeclarationHaveABody ()) {
2601- copyCtor = declCtor;
2602- break ;
2630+ if (declCtor->isCopyConstructor ()) {
2631+ copyCtor = declCtor;
2632+ break ;
2633+ } else if (declCtor->isMoveConstructor ()) {
2634+ moveCtor = declCtor;
2635+ break ;
2636+ }
26032637 }
26042638 }
26052639 }
@@ -2608,14 +2642,27 @@ namespace {
26082642 clangSema.DefineImplicitCopyConstructor (clang::SourceLocation (),
26092643 copyCtor);
26102644 }
2645+ if (moveCtor) {
2646+ clangSema.DefineImplicitMoveConstructor (clang::SourceLocation (),
2647+ moveCtor);
2648+ }
2649+
2650+ if (decl->needsImplicitDestructor ()) {
2651+ auto dtor = clangSema.DeclareImplicitDestructor (
2652+ const_cast <clang::CXXRecordDecl *>(decl));
2653+ clangSema.DefineImplicitDestructor (clang::SourceLocation (), dtor);
2654+ }
26112655 }
26122656
26132657 // It is import that we bail on an unimportable record *before* we import
26142658 // any of its members or cache the decl.
26152659 auto semanticsKind =
26162660 evaluateOrDefault (Impl.SwiftContext .evaluator ,
26172661 CxxRecordSemantics ({decl, Impl.SwiftContext }), {});
2618- if (semanticsKind == CxxRecordSemanticsKind::MissingLifetimeOperation) {
2662+ if (semanticsKind == CxxRecordSemanticsKind::MissingLifetimeOperation &&
2663+ // Let un-specialized class templates through. We'll sort out their
2664+ // members once they're instranciated.
2665+ !Impl.importSymbolicCXXDecls ) {
26192666 Impl.addImportDiagnostic (
26202667 decl,
26212668 Diagnostic (diag::record_not_automatically_importable,
0 commit comments