Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 4 additions & 11 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3105,14 +3105,13 @@ namespace {
// instantiate its copy constructor.
bool isExplicitlyNonCopyable = hasNonCopyableAttr(decl);

clang::CXXConstructorDecl *moveCtor = nullptr;
clang::CXXConstructorDecl *defaultCtor = nullptr;
if (decl->needsImplicitCopyConstructor() && !isExplicitlyNonCopyable) {
clangSema.DeclareImplicitCopyConstructor(
const_cast<clang::CXXRecordDecl *>(decl));
}
if (decl->needsImplicitMoveConstructor()) {
moveCtor = clangSema.DeclareImplicitMoveConstructor(
clangSema.DeclareImplicitMoveConstructor(
const_cast<clang::CXXRecordDecl *>(decl));
}
if (decl->needsImplicitDefaultConstructor()) {
Expand All @@ -3129,20 +3128,13 @@ namespace {
// Note: we use "doesThisDeclarationHaveABody" here because
// that's what "DefineImplicitCopyConstructor" checks.
!declCtor->doesThisDeclarationHaveABody()) {
if (declCtor->isMoveConstructor()) {
if (!moveCtor)
moveCtor = declCtor;
} else if (declCtor->isDefaultConstructor()) {
if (declCtor->isDefaultConstructor()) {
if (!defaultCtor)
defaultCtor = declCtor;
}
}
}
}
if (moveCtor && !decl->isAnonymousStructOrUnion()) {
clangSema.DefineImplicitMoveConstructor(clang::SourceLocation(),
moveCtor);
}
if (defaultCtor) {
clangSema.DefineImplicitDefaultConstructor(clang::SourceLocation(),
defaultCtor);
Expand All @@ -3151,7 +3143,8 @@ namespace {
if (decl->needsImplicitDestructor()) {
auto dtor = clangSema.DeclareImplicitDestructor(
const_cast<clang::CXXRecordDecl *>(decl));
clangSema.DefineImplicitDestructor(clang::SourceLocation(), dtor);
if (!dtor->isDeleted() && !dtor->isIneligibleOrNotSelected())
clangSema.DefineImplicitDestructor(clang::SourceLocation(), dtor);
}
}

Expand Down
49 changes: 27 additions & 22 deletions lib/IRGen/GenStruct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ namespace {
/*invocation subs*/ SubstitutionMap(), IGF.IGM.Context);
}

void emitCopyWithCopyConstructor(
void emitCopyWithCopyOrMoveConstructor(
IRGenFunction &IGF, SILType T,
const clang::CXXConstructorDecl *copyConstructor, llvm::Value *src,
llvm::Value *dest) const {
Expand All @@ -625,12 +625,21 @@ namespace {
if (copyConstructor->isDefaulted() &&
copyConstructor->getAccess() == clang::AS_public &&
!copyConstructor->isDeleted() &&
!copyConstructor->isIneligibleOrNotSelected() &&
// Note: we use "doesThisDeclarationHaveABody" here because
// that's what "DefineImplicitCopyConstructor" checks.
!copyConstructor->doesThisDeclarationHaveABody()) {
importer->getClangSema().DefineImplicitCopyConstructor(
clang::SourceLocation(),
const_cast<clang::CXXConstructorDecl *>(copyConstructor));
assert(!copyConstructor->getParent()->isAnonymousStructOrUnion() &&
"Cannot do codegen of special member functions of anonymous "
"structs/unions");
if (copyConstructor->isCopyConstructor())
importer->getClangSema().DefineImplicitCopyConstructor(
clang::SourceLocation(),
const_cast<clang::CXXConstructorDecl *>(copyConstructor));
else
importer->getClangSema().DefineImplicitMoveConstructor(
clang::SourceLocation(),
const_cast<clang::CXXConstructorDecl *>(copyConstructor));
}

auto &diagEngine = importer->getClangSema().getDiagnostics();
Expand Down Expand Up @@ -812,9 +821,9 @@ namespace {
Address srcAddr, SILType T,
bool isOutlined) const override {
if (auto copyConstructor = findCopyConstructor()) {
emitCopyWithCopyConstructor(IGF, T, copyConstructor,
srcAddr.getAddress(),
destAddr.getAddress());
emitCopyWithCopyOrMoveConstructor(IGF, T, copyConstructor,
srcAddr.getAddress(),
destAddr.getAddress());
return;
}
StructTypeInfoBase<AddressOnlyCXXClangRecordTypeInfo, FixedTypeInfo,
Expand All @@ -827,9 +836,9 @@ namespace {
SILType T, bool isOutlined) const override {
if (auto copyConstructor = findCopyConstructor()) {
destroy(IGF, destAddr, T, isOutlined);
emitCopyWithCopyConstructor(IGF, T, copyConstructor,
srcAddr.getAddress(),
destAddr.getAddress());
emitCopyWithCopyOrMoveConstructor(IGF, T, copyConstructor,
srcAddr.getAddress(),
destAddr.getAddress());
return;
}
StructTypeInfoBase<AddressOnlyCXXClangRecordTypeInfo, FixedTypeInfo,
Expand All @@ -841,17 +850,15 @@ namespace {
SILType T, bool isOutlined,
bool zeroizeIfSensitive) const override {
if (auto moveConstructor = findMoveConstructor()) {
emitCopyWithCopyConstructor(IGF, T, moveConstructor,
src.getAddress(),
dest.getAddress());
emitCopyWithCopyOrMoveConstructor(IGF, T, moveConstructor,
src.getAddress(), dest.getAddress());
destroy(IGF, src, T, isOutlined);
return;
}

if (auto copyConstructor = findCopyConstructor()) {
emitCopyWithCopyConstructor(IGF, T, copyConstructor,
src.getAddress(),
dest.getAddress());
emitCopyWithCopyOrMoveConstructor(IGF, T, copyConstructor,
src.getAddress(), dest.getAddress());
destroy(IGF, src, T, isOutlined);
return;
}
Expand All @@ -865,18 +872,16 @@ namespace {
bool isOutlined) const override {
if (auto moveConstructor = findMoveConstructor()) {
destroy(IGF, dest, T, isOutlined);
emitCopyWithCopyConstructor(IGF, T, moveConstructor,
src.getAddress(),
dest.getAddress());
emitCopyWithCopyOrMoveConstructor(IGF, T, moveConstructor,
src.getAddress(), dest.getAddress());
destroy(IGF, src, T, isOutlined);
return;
}

if (auto copyConstructor = findCopyConstructor()) {
destroy(IGF, dest, T, isOutlined);
emitCopyWithCopyConstructor(IGF, T, copyConstructor,
src.getAddress(),
dest.getAddress());
emitCopyWithCopyOrMoveConstructor(IGF, T, copyConstructor,
src.getAddress(), dest.getAddress());
destroy(IGF, src, T, isOutlined);
return;
}
Expand Down
6 changes: 6 additions & 0 deletions test/Interop/Cxx/stdlib/Inputs/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,9 @@ module CustomSmartPtr {
requires cplusplus
export *
}

module StdExpected {
header "std-expected.h"
requires cplusplus
export *
}
23 changes: 23 additions & 0 deletions test/Interop/Cxx/stdlib/Inputs/std-expected.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef TEST_INTEROP_CXX_STDLIB_INPUTS_STD_UNIQUE_PTR_H
#define TEST_INTEROP_CXX_STDLIB_INPUTS_STD_UNIQUE_PTR_H

#include <memory>
#include <expected>

using NonCopyableExpected = std::expected<std::unique_ptr<bool>, int>;

template<typename T>
class UniqueRef {
public:
std::unique_ptr<T> _field;
};

struct Decoder {};
enum Error {
DoomA,
DoomB
};

using DecoderOrError = std::expected<UniqueRef<Decoder>, Error>;

#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_UNIQUE_PTR_H
22 changes: 22 additions & 0 deletions test/Interop/Cxx/stdlib/use-std-expected-typechecker.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: not %target-swift-frontend %s -typecheck -I %S/Inputs -cxx-interoperability-mode=default -Xcc -std=c++23 -diagnostic-style llvm 2>&1 | %FileCheck %s

// TODO <expected> not yet supported with libstdc++
// XFAIL: OS=linux-gnu

// https://github.com/apple/swift/issues/70226
// UNSUPPORTED: OS=windows-msvc

import StdExpected
import CxxStdlib

func takeCopyable<T: Copyable>(_ x: T) {}

let nonCopExpected = NonCopyableExpected()
takeCopyable(nonCopExpected)
// CHECK: error: global function 'takeCopyable' requires that 'NonCopyableExpected' (aka {{.*}}) conform to 'Copyable'

let doe = DecoderOrError()
takeCopyable(doe)
// CHECK: error: global function 'takeCopyable' requires that 'DecoderOrError' (aka {{.*}}) conform to 'Copyable'

// CHECK-NOT: error