Skip to content

Commit 35e7db5

Browse files
committed
[cxx-interop] Prevent usage in Swift of C++ copy constructor with default args
1 parent 8daf94c commit 35e7db5

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7851,6 +7851,14 @@ static bool isSufficientlyTrivial(const clang::CXXRecordDecl *decl) {
78517851
return true;
78527852
}
78537853

7854+
static bool hasDefaultArgs(const clang::CXXConstructorDecl *ctor) {
7855+
if (ctor->param_empty()) {
7856+
return false;
7857+
}
7858+
auto lastParam = ctor->parameters().back();
7859+
return lastParam->hasDefaultArg();
7860+
}
7861+
78547862
/// Checks if a record provides the required value type lifetime operations
78557863
/// (copy and destroy).
78567864
static bool hasCopyTypeOperations(const clang::CXXRecordDecl *decl) {
@@ -7867,6 +7875,7 @@ static bool hasCopyTypeOperations(const clang::CXXRecordDecl *decl) {
78677875
// struct.
78687876
return llvm::any_of(decl->ctors(), [](clang::CXXConstructorDecl *ctor) {
78697877
return ctor->isCopyConstructor() && !ctor->isDeleted() &&
7878+
!hasDefaultArgs(ctor) &&
78707879
ctor->getAccess() == clang::AccessSpecifier::AS_public;
78717880
});
78727881
}

test/Interop/Cxx/value-witness-table/Inputs/copy-constructors.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ struct HasNonTrivialDefaultCopyConstructor {
2323
const HasNonTrivialDefaultCopyConstructor &) = default;
2424
};
2525

26+
struct HasCopyConstructorWithDefaultArgs {
27+
int value;
28+
HasCopyConstructorWithDefaultArgs(int value) : value(value) {}
29+
30+
HasCopyConstructorWithDefaultArgs(
31+
const HasCopyConstructorWithDefaultArgs &other, int value = 1)
32+
: value(other.value + value) {}
33+
34+
HasCopyConstructorWithDefaultArgs(HasCopyConstructorWithDefaultArgs &&) =
35+
default;
36+
};
37+
2638
// Make sure that we don't crash on struct templates with copy-constructors.
2739
template <typename T> struct S {
2840
S(S const &) {}

test/Interop/Cxx/value-witness-table/copy-constructors-execution.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,16 @@ CXXCopyConstructorTestSuite.test("Default copy constructor, member with user-def
4848
expectTrue(result.0.box.numCopies + result.1.box.numCopies > 0)
4949
}
5050

51+
CXXCopyConstructorTestSuite.test("Copy constructor with default args") {
52+
@inline(never)
53+
54+
// When in the presence of a C++ copy constructor with default args, we make the type non-copyable
55+
let originalObj = HasCopyConstructorWithDefaultArgs(5)
56+
expectEqual(originalObj.value, 5)
57+
58+
// move originalObj
59+
let newObj = originalObj
60+
expectEqual(newObj.value, 5)
61+
}
62+
5163
runAllTests()

0 commit comments

Comments
 (0)