Skip to content

Commit cd01e91

Browse files
authored
Merge pull request #84121 from susmonteiro/susmonteiro/copy-operations-requires-clause
[cxx-interop] Check if copy constructor is eligible
2 parents 763d71d + 96d0018 commit cd01e91

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
@@ -8175,6 +8175,7 @@ static bool hasCopyTypeOperations(const clang::CXXRecordDecl *decl) {
81758175
// struct.
81768176
return llvm::any_of(decl->ctors(), [](clang::CXXConstructorDecl *ctor) {
81778177
return ctor->isCopyConstructor() && !ctor->isDeleted() &&
8178+
!ctor->isIneligibleOrNotSelected() &&
81788179
// FIXME: Support default arguments (rdar://142414553)
81798180
ctor->getNumParams() == 1 &&
81808181
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)