Skip to content

Commit 96d0018

Browse files
committed
[cxx-interop] Check if copy constructor is eligible
1 parent a1d18cf commit 96d0018

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8164,6 +8164,7 @@ static bool hasCopyTypeOperations(const clang::CXXRecordDecl *decl) {
81648164
// struct.
81658165
return llvm::any_of(decl->ctors(), [](clang::CXXConstructorDecl *ctor) {
81668166
return ctor->isCopyConstructor() && !ctor->isDeleted() &&
8167+
!ctor->isIneligibleOrNotSelected() &&
81678168
// FIXME: Support default arguments (rdar://142414553)
81688169
ctor->getNumParams() == 1 &&
81698170
ctor->getAccess() == clang::AccessSpecifier::AS_public;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
// RUN: %target-swift-frontend -cxx-interoperability-mode=default -typecheck -verify - -I %t/Inputs %t/test.swift
4+
// RUN: %target-swift-frontend -cxx-interoperability-mode=default -Xcc -std=c++20 -verify-additional-prefix cpp20- -D CPP20 -typecheck -verify -I %t/Inputs %t/test.swift
5+
6+
//--- Inputs/module.modulemap
7+
module Test {
8+
header "noncopyable.h"
9+
requires cplusplus
10+
}
11+
12+
//--- Inputs/noncopyable.h
13+
#include <string>
14+
15+
struct NonCopyable {
16+
NonCopyable() = default;
17+
NonCopyable(const NonCopyable& other) = delete;
18+
NonCopyable(NonCopyable&& other) = default;
19+
};
20+
21+
template <typename T>
22+
struct OwnsT {
23+
T element;
24+
OwnsT() {}
25+
OwnsT(const OwnsT &other) : element(other.element) {}
26+
OwnsT(OwnsT&& other) {}
27+
};
28+
29+
using OwnsNonCopyable = OwnsT<NonCopyable>;
30+
31+
#if __cplusplus >= 202002L
32+
template <typename T>
33+
struct RequiresCopyableT {
34+
T element;
35+
RequiresCopyableT() {}
36+
RequiresCopyableT(const RequiresCopyableT &other) requires std::is_copy_constructible_v<T> : element(other.element) {}
37+
RequiresCopyableT(RequiresCopyableT&& other) {}
38+
};
39+
40+
using NonCopyableRequires = RequiresCopyableT<NonCopyable>;
41+
42+
#endif
43+
44+
//--- test.swift
45+
import Test
46+
import CxxStdlib
47+
48+
func takeCopyable<T: Copyable>(_ x: T) {}
49+
// expected-note@-1 {{'where T: Copyable' is implicit here}}
50+
// expected-cpp20-note@-2 {{'where T: Copyable' is implicit here}}
51+
52+
func userDefinedTypes() {
53+
let nCop = NonCopyable()
54+
takeCopyable(nCop) // expected-error {{global function 'takeCopyable' requires that 'NonCopyable' conform to 'Copyable'}}
55+
56+
let ownsT = OwnsNonCopyable()
57+
takeCopyable(ownsT) // no error, OwnsNonCopyable imported as Copyable
58+
59+
}
60+
61+
#if CPP20
62+
func useOfRequires() {
63+
let nCop = NonCopyableRequires()
64+
takeCopyable(nCop) // expected-cpp20-error {{global function 'takeCopyable' requires that 'NonCopyableRequires' (aka 'RequiresCopyableT<NonCopyable>') conform to 'Copyable'}}
65+
}
66+
#endif
67+

0 commit comments

Comments
 (0)