Skip to content

Commit 6ee641a

Browse files
committed
[cxx-interop] Implicitly defined move constructors
1 parent 94949f3 commit 6ee641a

File tree

5 files changed

+62
-14
lines changed

5 files changed

+62
-14
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3105,14 +3105,13 @@ namespace {
31053105
// instantiate its copy constructor.
31063106
bool isExplicitlyNonCopyable = hasNonCopyableAttr(decl);
31073107

3108-
clang::CXXConstructorDecl *moveCtor = nullptr;
31093108
clang::CXXConstructorDecl *defaultCtor = nullptr;
31103109
if (decl->needsImplicitCopyConstructor() && !isExplicitlyNonCopyable) {
31113110
clangSema.DeclareImplicitCopyConstructor(
31123111
const_cast<clang::CXXRecordDecl *>(decl));
31133112
}
31143113
if (decl->needsImplicitMoveConstructor()) {
3115-
moveCtor = clangSema.DeclareImplicitMoveConstructor(
3114+
clangSema.DeclareImplicitMoveConstructor(
31163115
const_cast<clang::CXXRecordDecl *>(decl));
31173116
}
31183117
if (decl->needsImplicitDefaultConstructor()) {
@@ -3129,20 +3128,13 @@ namespace {
31293128
// Note: we use "doesThisDeclarationHaveABody" here because
31303129
// that's what "DefineImplicitCopyConstructor" checks.
31313130
!declCtor->doesThisDeclarationHaveABody()) {
3132-
if (declCtor->isMoveConstructor()) {
3133-
if (!moveCtor)
3134-
moveCtor = declCtor;
3135-
} else if (declCtor->isDefaultConstructor()) {
3131+
if (declCtor->isDefaultConstructor()) {
31363132
if (!defaultCtor)
31373133
defaultCtor = declCtor;
31383134
}
31393135
}
31403136
}
31413137
}
3142-
if (moveCtor && !decl->isAnonymousStructOrUnion()) {
3143-
clangSema.DefineImplicitMoveConstructor(clang::SourceLocation(),
3144-
moveCtor);
3145-
}
31463138
if (defaultCtor) {
31473139
clangSema.DefineImplicitDefaultConstructor(clang::SourceLocation(),
31483140
defaultCtor);
@@ -3151,7 +3143,8 @@ namespace {
31513143
if (decl->needsImplicitDestructor()) {
31523144
auto dtor = clangSema.DeclareImplicitDestructor(
31533145
const_cast<clang::CXXRecordDecl *>(decl));
3154-
clangSema.DefineImplicitDestructor(clang::SourceLocation(), dtor);
3146+
if (!dtor->isDeleted() && !dtor->isIneligibleOrNotSelected())
3147+
clangSema.DefineImplicitDestructor(clang::SourceLocation(), dtor);
31553148
}
31563149
}
31573150

lib/IRGen/GenStruct.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -625,12 +625,19 @@ namespace {
625625
if (copyConstructor->isDefaulted() &&
626626
copyConstructor->getAccess() == clang::AS_public &&
627627
!copyConstructor->isDeleted() &&
628+
!copyConstructor->isIneligibleOrNotSelected() &&
629+
!copyConstructor->getParent()->isAnonymousStructOrUnion() &&
628630
// Note: we use "doesThisDeclarationHaveABody" here because
629631
// that's what "DefineImplicitCopyConstructor" checks.
630632
!copyConstructor->doesThisDeclarationHaveABody()) {
631-
importer->getClangSema().DefineImplicitCopyConstructor(
632-
clang::SourceLocation(),
633-
const_cast<clang::CXXConstructorDecl *>(copyConstructor));
633+
if (copyConstructor->isCopyConstructor())
634+
importer->getClangSema().DefineImplicitCopyConstructor(
635+
clang::SourceLocation(),
636+
const_cast<clang::CXXConstructorDecl *>(copyConstructor));
637+
else
638+
importer->getClangSema().DefineImplicitMoveConstructor(
639+
clang::SourceLocation(),
640+
const_cast<clang::CXXConstructorDecl *>(copyConstructor));
634641
}
635642

636643
auto &diagEngine = importer->getClangSema().getDiagnostics();

test/Interop/Cxx/stdlib/Inputs/module.modulemap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,9 @@ module CustomSmartPtr {
9999
requires cplusplus
100100
export *
101101
}
102+
103+
module StdExpected {
104+
header "std-expected.h"
105+
requires cplusplus
106+
export *
107+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef TEST_INTEROP_CXX_STDLIB_INPUTS_STD_UNIQUE_PTR_H
2+
#define TEST_INTEROP_CXX_STDLIB_INPUTS_STD_UNIQUE_PTR_H
3+
4+
#include <memory>
5+
#include <expected>
6+
7+
using NonCopyableExpected = std::expected<std::unique_ptr<bool>, int>;
8+
9+
template<typename T>
10+
class UniqueRef {
11+
public:
12+
std::unique_ptr<T> _field;
13+
};
14+
15+
struct Decoder {};
16+
enum Error {
17+
DoomA,
18+
DoomB
19+
};
20+
21+
using DecoderOrError = std::expected<UniqueRef<Decoder>, Error>;
22+
23+
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_UNIQUE_PTR_H
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: not %target-swift-frontend %s -typecheck -I %S/Inputs -cxx-interoperability-mode=default -Xcc -std=c++23 -diagnostic-style llvm 2>&1 | %FileCheck %s
2+
3+
// TODO Linux CI stdlib doesn't support std::expected yet
4+
// XFAIL: OS=linux-gnu
5+
6+
import StdExpected
7+
import CxxStdlib
8+
9+
func takeCopyable<T: Copyable>(_ x: T) {}
10+
11+
let nonCopExpected = NonCopyableExpected()
12+
takeCopyable(nonCopExpected)
13+
// CHECK: error: global function 'takeCopyable' requires that 'NonCopyableExpected' (aka {{.*}}) conform to 'Copyable'
14+
15+
let doe = DecoderOrError()
16+
takeCopyable(doe)
17+
// CHECK: error: global function 'takeCopyable' requires that 'DecoderOrError' (aka {{.*}}) conform to 'Copyable'
18+
19+
// CHECK-NOT: error

0 commit comments

Comments
 (0)