Skip to content

Commit 2c9bb7a

Browse files
committed
Revert "[cxx-interop] Implicitly defined copy constructors"
This reverts commit 1c5bbe0.
1 parent dd921ad commit 2c9bb7a

File tree

8 files changed

+46
-147
lines changed

8 files changed

+46
-147
lines changed

include/swift/ClangImporter/ClangImporter.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -733,12 +733,6 @@ ValueDecl *getImportedMemberOperator(const DeclBaseName &name,
733733
/// as permissive as the input C++ access.
734734
AccessLevel convertClangAccess(clang::AccessSpecifier access);
735735

736-
/// Lookup and return the copy constructor of \a decl
737-
///
738-
/// Returns nullptr if \a decl doesn't have a valid copy constructor
739-
const clang::CXXConstructorDecl *
740-
findCopyConstructor(const clang::CXXRecordDecl *decl);
741-
742736
/// Read file IDs from 'private_fileid' Swift attributes on a Clang decl.
743737
///
744738
/// May return >1 fileID when a decl is annotated more than once, which should

lib/ClangImporter/ClangImporter.cpp

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8322,39 +8322,16 @@ bool importer::isViewType(const clang::CXXRecordDecl *decl) {
83228322
return !hasOwnedValueAttr(decl) && hasPointerInSubobjects(decl);
83238323
}
83248324

8325-
const clang::CXXConstructorDecl *
8326-
importer::findCopyConstructor(const clang::CXXRecordDecl *decl) {
8327-
for (auto ctor : decl->ctors()) {
8328-
if (ctor->isCopyConstructor() &&
8329-
// FIXME: Support default arguments (rdar://142414553)
8330-
ctor->getNumParams() == 1 && ctor->getAccess() == clang::AS_public &&
8331-
!ctor->isDeleted() && !ctor->isIneligibleOrNotSelected())
8332-
return ctor;
8333-
}
8334-
return nullptr;
8335-
}
8336-
8337-
static bool hasCopyTypeOperations(const clang::CXXRecordDecl *decl,
8338-
ClangImporter::Implementation *importerImpl) {
8339-
if (!decl->hasSimpleCopyConstructor()) {
8340-
auto *copyCtor = findCopyConstructor(decl);
8341-
if (!copyCtor)
8342-
return false;
8343-
8344-
if (!copyCtor->isDefaulted())
8345-
return true;
8346-
}
8325+
static bool hasCopyTypeOperations(const clang::CXXRecordDecl *decl) {
8326+
if (decl->hasSimpleCopyConstructor())
8327+
return true;
83478328

8348-
// If the copy constructor is defaulted or implicitly declared, we should only
8349-
// import the type as copyable if all its fields are also copyable
8350-
// FIXME: we should also look at the bases
8351-
return llvm::none_of(decl->fields(), [&](clang::FieldDecl *field) {
8352-
if (const auto *rd = field->getType()->getAsRecordDecl()) {
8353-
return (!field->getType()->isReferenceType() &&
8354-
!field->getType()->isPointerType() &&
8355-
recordHasMoveOnlySemantics(rd, importerImpl));
8356-
}
8357-
return false;
8329+
return llvm::any_of(decl->ctors(), [](clang::CXXConstructorDecl *ctor) {
8330+
return ctor->isCopyConstructor() && !ctor->isDeleted() &&
8331+
!ctor->isIneligibleOrNotSelected() &&
8332+
// FIXME: Support default arguments (rdar://142414553)
8333+
ctor->getNumParams() == 1 &&
8334+
ctor->getAccess() == clang::AccessSpecifier::AS_public;
83588335
});
83598336
}
83608337

@@ -8553,8 +8530,8 @@ CxxValueSemantics::evaluate(Evaluator &evaluator,
85538530
return CxxValueSemanticsKind::Copyable;
85548531
}
85558532

8556-
bool isCopyable = !hasNonCopyableAttr(cxxRecordDecl) &&
8557-
hasCopyTypeOperations(cxxRecordDecl, importerImpl);
8533+
bool isCopyable = !hasNonCopyableAttr(cxxRecordDecl) &&
8534+
hasCopyTypeOperations(cxxRecordDecl);
85588535
bool isMovable = hasMoveTypeOperations(cxxRecordDecl);
85598536

85608537
if (!hasDestroyTypeOperations(cxxRecordDecl) || (!isCopyable && !isMovable)) {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,6 @@ bool importer::recordHasReferenceSemantics(
186186
return semanticsKind == CxxRecordSemanticsKind::Reference;
187187
}
188188

189-
bool importer::recordHasMoveOnlySemantics(
190-
const clang::RecordDecl *decl,
191-
ClangImporter::Implementation *importerImpl) {
192-
auto semanticsKind = evaluateOrDefault(
193-
importerImpl->SwiftContext.evaluator,
194-
CxxValueSemantics({decl->getTypeForDecl(), importerImpl}), {});
195-
return semanticsKind == CxxValueSemanticsKind::MoveOnly;
196-
}
197-
198189
bool importer::hasImmortalAttrs(const clang::RecordDecl *decl) {
199190
return decl->hasAttrs() && llvm::any_of(decl->getAttrs(), [](auto *attr) {
200191
if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
@@ -2104,7 +2095,10 @@ namespace {
21042095
}
21052096

21062097
bool recordHasMoveOnlySemantics(const clang::RecordDecl *decl) {
2107-
return importer::recordHasMoveOnlySemantics(decl, &Impl);
2098+
auto semanticsKind = evaluateOrDefault(
2099+
Impl.SwiftContext.evaluator,
2100+
CxxValueSemantics({decl->getTypeForDecl(), &Impl}), {});
2101+
return semanticsKind == CxxValueSemanticsKind::MoveOnly;
21082102
}
21092103

21102104
void markReturnsUnsafeNonescapable(AbstractFunctionDecl *fd) {
@@ -2283,9 +2277,13 @@ namespace {
22832277
loc, ArrayRef<InheritedEntry>(), nullptr, dc);
22842278
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
22852279

2286-
if (decl->isInStdNamespace() && decl->getName() == "promise" && recordHasMoveOnlySemantics(decl)) {
2287-
// Do not import std::promise.
2288-
return nullptr;
2280+
if (recordHasMoveOnlySemantics(decl)) {
2281+
if (decl->isInStdNamespace() && decl->getName() == "promise") {
2282+
// Do not import std::promise.
2283+
return nullptr;
2284+
}
2285+
result->addAttribute(new (Impl.SwiftContext)
2286+
MoveOnlyAttr(/*Implicit=*/true));
22892287
}
22902288

22912289
// FIXME: Figure out what to do with superclasses in C++. One possible
@@ -2532,11 +2530,6 @@ namespace {
25322530
cxxRecordDecl->ctors().empty());
25332531
}
25342532

2535-
if (recordHasMoveOnlySemantics(decl)) {
2536-
result->getAttrs().add(new (Impl.SwiftContext)
2537-
MoveOnlyAttr(/*Implicit=*/true));
2538-
}
2539-
25402533
// TODO: builtin "zeroInitializer" does not work with non-escapable
25412534
// types yet. Don't generate an initializer.
25422535
if (hasZeroInitializableStorage && needsEmptyInitializer &&
@@ -3132,10 +3125,11 @@ namespace {
31323125
// instantiate its copy constructor.
31333126
bool isExplicitlyNonCopyable = hasNonCopyableAttr(decl);
31343127

3128+
clang::CXXConstructorDecl *copyCtor = nullptr;
31353129
clang::CXXConstructorDecl *moveCtor = nullptr;
31363130
clang::CXXConstructorDecl *defaultCtor = nullptr;
31373131
if (decl->needsImplicitCopyConstructor() && !isExplicitlyNonCopyable) {
3138-
clangSema.DeclareImplicitCopyConstructor(
3132+
copyCtor = clangSema.DeclareImplicitCopyConstructor(
31393133
const_cast<clang::CXXRecordDecl *>(decl));
31403134
}
31413135
if (decl->needsImplicitMoveConstructor()) {
@@ -3156,7 +3150,10 @@ namespace {
31563150
// Note: we use "doesThisDeclarationHaveABody" here because
31573151
// that's what "DefineImplicitCopyConstructor" checks.
31583152
!declCtor->doesThisDeclarationHaveABody()) {
3159-
if (declCtor->isMoveConstructor()) {
3153+
if (declCtor->isCopyConstructor()) {
3154+
if (!copyCtor && !isExplicitlyNonCopyable)
3155+
copyCtor = declCtor;
3156+
} else if (declCtor->isMoveConstructor()) {
31603157
if (!moveCtor)
31613158
moveCtor = declCtor;
31623159
} else if (declCtor->isDefaultConstructor()) {
@@ -3166,6 +3163,11 @@ namespace {
31663163
}
31673164
}
31683165
}
3166+
if (copyCtor && !isExplicitlyNonCopyable &&
3167+
!decl->isAnonymousStructOrUnion()) {
3168+
clangSema.DefineImplicitCopyConstructor(clang::SourceLocation(),
3169+
copyCtor);
3170+
}
31693171
if (moveCtor && !decl->isAnonymousStructOrUnion()) {
31703172
clangSema.DefineImplicitMoveConstructor(clang::SourceLocation(),
31713173
moveCtor);

lib/ClangImporter/ImporterImpl.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,11 +1974,6 @@ namespace importer {
19741974
bool recordHasReferenceSemantics(const clang::RecordDecl *decl,
19751975
ClangImporter::Implementation *importerImpl);
19761976

1977-
/// Returns true if the given C/C++ record should be imported as non-copyable into
1978-
/// Swift.
1979-
bool recordHasMoveOnlySemantics(const clang::RecordDecl *decl,
1980-
ClangImporter::Implementation *importerImpl);
1981-
19821977
/// Whether this is a forward declaration of a type. We ignore forward
19831978
/// declarations in certain cases, and instead process the real declarations.
19841979
bool isForwardDeclOfType(const clang::Decl *decl);

lib/IRGen/GenStruct.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,15 @@ namespace {
553553
const auto *cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(ClangDecl);
554554
if (!cxxRecordDecl)
555555
return nullptr;
556-
return importer::findCopyConstructor(cxxRecordDecl);
556+
for (auto ctor : cxxRecordDecl->ctors()) {
557+
if (ctor->isCopyConstructor() &&
558+
// FIXME: Support default arguments (rdar://142414553)
559+
ctor->getNumParams() == 1 &&
560+
ctor->getAccess() == clang::AS_public && !ctor->isDeleted() &&
561+
!ctor->isIneligibleOrNotSelected())
562+
return ctor;
563+
}
564+
return nullptr;
557565
}
558566

559567
const clang::CXXConstructorDecl *findMoveConstructor() const {
@@ -621,18 +629,7 @@ namespace {
621629

622630
auto &ctx = IGF.IGM.Context;
623631
auto *importer = static_cast<ClangImporter *>(ctx.getClangModuleLoader());
624-
625-
if (copyConstructor->isDefaulted() &&
626-
copyConstructor->getAccess() == clang::AS_public &&
627-
!copyConstructor->isDeleted() &&
628-
// Note: we use "doesThisDeclarationHaveABody" here because
629-
// that's what "DefineImplicitCopyConstructor" checks.
630-
!copyConstructor->doesThisDeclarationHaveABody()) {
631-
importer->getClangSema().DefineImplicitCopyConstructor(
632-
clang::SourceLocation(),
633-
const_cast<clang::CXXConstructorDecl *>(copyConstructor));
634-
}
635-
632+
636633
auto &diagEngine = importer->getClangSema().getDiagnostics();
637634
clang::DiagnosticErrorTrap trap(diagEngine);
638635
auto clangFnAddr =

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

Lines changed: 3 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %empty-directory(%t)
22
// RUN: split-file %s %t
3-
// RUN: %target-swift-frontend -cxx-interoperability-mode=default -typecheck -verify -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t%{fs-sep}Inputs %t%{fs-sep}test.swift -verify-additional-file %t%{fs-sep}Inputs%{fs-sep}noncopyable.h -verify-ignore-unrelated
4-
// RUN: %target-swift-frontend -cxx-interoperability-mode=default -Xcc -std=c++20 -verify-additional-prefix cpp20- -D CPP20 -typecheck -verify -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t%{fs-sep}Inputs %t%{fs-sep}test.swift -verify-additional-file %t%{fs-sep}Inputs%{fs-sep}noncopyable.h -verify-ignore-unrelated
3+
// RUN: %target-swift-frontend -cxx-interoperability-mode=default -typecheck -verify -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t%{fs-sep}Inputs %t%{fs-sep}test.swift -verify-additional-file %t%{fs-sep}Inputs%{fs-sep}noncopyable.h
4+
// RUN: %target-swift-frontend -cxx-interoperability-mode=default -Xcc -std=c++20 -verify-additional-prefix cpp20- -D CPP20 -typecheck -verify -I %swift_src_root/lib/ClangImporter/SwiftBridging -I %t%{fs-sep}Inputs %t%{fs-sep}test.swift -verify-additional-file %t%{fs-sep}Inputs%{fs-sep}noncopyable.h
55

66
//--- Inputs/module.modulemap
77
module Test {
@@ -15,7 +15,7 @@ module Test {
1515

1616
struct NonCopyable {
1717
NonCopyable() = default;
18-
NonCopyable(const NonCopyable& other) = delete; // expected-note {{'NonCopyable' has been explicitly marked deleted here}}
18+
NonCopyable(const NonCopyable& other) = delete;
1919
NonCopyable(NonCopyable&& other) = default;
2020
};
2121

@@ -79,44 +79,6 @@ struct SWIFT_NONCOPYABLE NonCopyableNonMovable { // expected-note {{record 'NonC
7979
NonCopyableNonMovable(NonCopyableNonMovable&& other) = delete;
8080
};
8181

82-
struct ImplicitCopyConstructor {
83-
NonCopyable element;
84-
};
85-
86-
template <typename T, typename P, typename R>
87-
struct TemplatedImplicitCopyConstructor {
88-
T element;
89-
P *pointer;
90-
R &reference;
91-
};
92-
93-
using NonCopyableT = TemplatedImplicitCopyConstructor<NonCopyable, int, int>;
94-
using NonCopyableP = TemplatedImplicitCopyConstructor<int, NonCopyable, int>;
95-
using NonCopyableR = TemplatedImplicitCopyConstructor<int, int, NonCopyable>;
96-
97-
struct DefaultedCopyConstructor {
98-
NonCopyable element; // expected-note {{copy constructor of 'DefaultedCopyConstructor' is implicitly deleted because field 'element' has a deleted copy constructor}}
99-
DefaultedCopyConstructor(const DefaultedCopyConstructor&) = default;
100-
// expected-warning@-1 {{explicitly defaulted copy constructor is implicitly deleted}}
101-
// expected-note@-2 {{replace 'default' with 'delete'}}
102-
DefaultedCopyConstructor(DefaultedCopyConstructor&&) = default;
103-
};
104-
105-
template<typename T>
106-
struct TemplatedDefaultedCopyConstructor {
107-
T element;
108-
TemplatedDefaultedCopyConstructor(const TemplatedDefaultedCopyConstructor&) = default;
109-
TemplatedDefaultedCopyConstructor(TemplatedDefaultedCopyConstructor&&) = default;
110-
};
111-
112-
template<typename T>
113-
struct DerivedTemplatedDefaultedCopyConstructor : TemplatedDefaultedCopyConstructor<T> {};
114-
115-
using CopyableDefaultedCopyConstructor = TemplatedDefaultedCopyConstructor<NonCopyableP>;
116-
using NonCopyableDefaultedCopyConstructor = TemplatedDefaultedCopyConstructor<NonCopyable>;
117-
using CopyableDerived = DerivedTemplatedDefaultedCopyConstructor<NonCopyableR>;
118-
using NonCopyableDerived = DerivedTemplatedDefaultedCopyConstructor<NonCopyable>;
119-
12082
template<typename T> struct SWIFT_COPYABLE_IF(T) DisposableContainer {};
12183
struct POD { int x; float y; }; // special members are implicit, but should be copyable
12284
using DisposablePOD = DisposableContainer<POD>; // should also be copyable
@@ -171,23 +133,6 @@ func missingLifetimeOperation() {
171133
takeCopyable(s)
172134
}
173135

174-
func implicitCopyConstructor(i: borrowing ImplicitCopyConstructor, t: borrowing NonCopyableT, p: borrowing NonCopyableP, r: borrowing NonCopyableR) {
175-
takeCopyable(i) // expected-error {{global function 'takeCopyable' requires that 'ImplicitCopyConstructor' conform to 'Copyable'}}
176-
takeCopyable(t) // expected-error {{global function 'takeCopyable' requires that 'NonCopyableT' (aka 'TemplatedImplicitCopyConstructor<NonCopyable, CInt, CInt>') conform to 'Copyable'}}
177-
178-
// References and pointers to non-copyable types are still copyable
179-
takeCopyable(p)
180-
takeCopyable(r)
181-
}
182-
183-
func defaultCopyConstructor(d: borrowing DefaultedCopyConstructor, d1: borrowing CopyableDefaultedCopyConstructor, d2: borrowing NonCopyableDefaultedCopyConstructor, d3: borrowing CopyableDerived, d4: borrowing NonCopyableDerived) {
184-
takeCopyable(d) // expected-error {{global function 'takeCopyable' requires that 'DefaultedCopyConstructor' conform to 'Copyable'}}
185-
takeCopyable(d1)
186-
takeCopyable(d2) // expected-error {{global function 'takeCopyable' requires that 'NonCopyableDefaultedCopyConstructor' (aka 'TemplatedDefaultedCopyConstructor<NonCopyable>') conform to 'Copyable'}}
187-
takeCopyable(d3)
188-
takeCopyable(d4) // expected-error {{global function 'takeCopyable' requires that 'NonCopyableDerived' (aka 'DerivedTemplatedDefaultedCopyConstructor<NonCopyable>') conform to 'Copyable'}}
189-
}
190-
191136
func copyableDisposablePOD(p: DisposablePOD) {
192137
takeCopyable(p)
193138
}

test/Interop/Cxx/stdlib/Inputs/std-unique-ptr.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,4 @@ struct CountCopies {
8989

9090
inline std::unique_ptr<CountCopies> getCopyCountedUniquePtr() { return std::make_unique<CountCopies>(); }
9191

92-
struct HasUniqueIntVector {
93-
HasUniqueIntVector() = default;
94-
std::vector<std::unique_ptr<int>> x;
95-
};
96-
9792
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_UNIQUE_PTR_H

test/Interop/Cxx/stdlib/use-std-unique-ptr-typechecker.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,3 @@ func takeCopyable<T: Copyable>(_ x: T) {}
1010
let vecUniquePtr = getVectorNonCopyableUniquePtr()
1111
takeCopyable(vecUniquePtr)
1212
// CHECK: error: global function 'takeCopyable' requires that 'std{{.*}}vector{{.*}}unique_ptr{{.*}}NonCopyable{{.*}}' conform to 'Copyable'
13-
14-
let uniqueIntVec = HasUniqueIntVector()
15-
takeCopyable(uniqueIntVec)
16-
// CHECK: error: global function 'takeCopyable' requires that 'HasUniqueIntVector' conform to 'Copyable'
17-
18-

0 commit comments

Comments
 (0)