Skip to content

Commit ffb22d7

Browse files
authored
Merge pull request #73297 from swiftlang/egorzhdan/correct-check-for-copy-ctor
[cxx-interop] Check the presence of copy constructor correctly
2 parents a7336e8 + fbbec48 commit ffb22d7

File tree

4 files changed

+41
-8
lines changed

4 files changed

+41
-8
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7625,18 +7625,22 @@ static bool hasCopyTypeOperations(const clang::CXXRecordDecl *decl) {
76257625
if (decl->isInStdNamespace() && decl->getIdentifier() &&
76267626
decl->getName() == "_Optional_construct_base")
76277627
return true;
7628+
// Hack for std::vector::const_iterator from libstdc++, which uses an extra
7629+
// parameter on its copy constructor, which has a defaulted enable_if value.
7630+
auto namespaceContext = dyn_cast_or_null<clang::NamespaceDecl>(
7631+
decl->getEnclosingNamespaceContext());
7632+
if (namespaceContext && namespaceContext->getIdentifier() &&
7633+
namespaceContext->getName() == "__gnu_cxx" && decl->getIdentifier() &&
7634+
decl->getName() == "__normal_iterator")
7635+
return true;
76287636

76297637
// If we have no way of copying the type we can't import the class
76307638
// at all because we cannot express the correct semantics as a swift
76317639
// struct.
7632-
if (llvm::any_of(decl->ctors(), [](clang::CXXConstructorDecl *ctor) {
7633-
return ctor->isCopyConstructor() &&
7634-
(ctor->isDeleted() || ctor->getAccess() != clang::AS_public);
7635-
}))
7636-
return false;
7637-
7638-
// TODO: this should probably check to make sure we actually have a copy ctor.
7639-
return true;
7640+
return llvm::any_of(decl->ctors(), [](clang::CXXConstructorDecl *ctor) {
7641+
return ctor->isCopyConstructor() && !ctor->isDeleted() &&
7642+
ctor->getAccess() == clang::AccessSpecifier::AS_public;
7643+
});
76407644
}
76417645

76427646
static bool hasMoveTypeOperations(const clang::CXXRecordDecl *decl) {

test/Interop/Cxx/class/Inputs/constructors.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,25 @@ struct TemplatedConstructorWithExtraArg {
7171
TemplatedConstructorWithExtraArg(T value, U other) { }
7272
};
7373

74+
struct TemplatedCopyConstructor {
75+
int x = 0;
76+
77+
TemplatedCopyConstructor(int x) : x(x) {}
78+
79+
template <class T>
80+
TemplatedCopyConstructor(const T &value) : x(value.x) {}
81+
};
82+
83+
struct TemplatedCopyConstructorWithExtraArg {
84+
int x = 0;
85+
86+
TemplatedCopyConstructorWithExtraArg(int x) : x(x) {}
87+
88+
template <class T>
89+
TemplatedCopyConstructorWithExtraArg(const T &value, int add = 0)
90+
: x(value.x + add) {}
91+
};
92+
7493
struct __attribute__((swift_attr("import_unsafe")))
7594
HasUserProvidedCopyConstructor {
7695
int numCopies;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// RUN: %target-swift-ide-test -print-module -module-to-print=Constructors -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s
22

3+
// CHECK: struct TemplatedCopyConstructor
4+
// CHECK: struct TemplatedCopyConstructorWithExtraArg
5+
36
// Make sure we don't import non-copyable types because we will have no way to
47
// represent and copy/move these in swift with correct semantics.
58
// CHECK-NOT: DeletedCopyConstructor

test/Interop/Cxx/class/constructors-typechecker.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import Constructors
44

5+
func takesCopyable<T: Copyable>(_ x: T.Type) {}
6+
57
let explicit = ExplicitDefaultConstructor()
68

79
let implicit = ImplicitDefaultConstructor()
@@ -12,3 +14,8 @@ let onlyCopyAndMove = CopyAndMoveConstructor() // expected-warning {{'init()' is
1214
let deletedExplicitly = DefaultConstructorDeleted() // expected-error {{missing argument for parameter 'a' in call}}
1315

1416
let withArg = ConstructorWithParam(42)
17+
18+
let _ = TemplatedCopyConstructor(123)
19+
let _ = TemplatedCopyConstructorWithExtraArg(123)
20+
takesCopyable(TemplatedCopyConstructor.self)
21+
takesCopyable(TemplatedCopyConstructorWithExtraArg.self)

0 commit comments

Comments
 (0)