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
13 changes: 7 additions & 6 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7368,12 +7368,6 @@ static bool hasDestroyTypeOperations(const clang::CXXRecordDecl *decl) {
}

static bool hasCustomCopyOrMoveConstructor(const clang::CXXRecordDecl *decl) {
// std::pair and std::tuple might have copy and move constructors, but that
// doesn't mean they are safe to use from Swift, e.g. std::pair<UnsafeType, T>
if (decl->isInStdNamespace() &&
(decl->getName() == "pair" || decl->getName() == "tuple")) {
return false;
}
return decl->hasUserDeclaredCopyConstructor() ||
decl->hasUserDeclaredMoveConstructor();
}
Expand Down Expand Up @@ -7489,6 +7483,13 @@ CxxRecordAsSwiftType::evaluate(Evaluator &evaluator,
}

bool anySubobjectsSelfContained(const clang::CXXRecordDecl *decl) {
// std::pair and std::tuple might have copy and move constructors, or base
// classes with copy and move constructors, but they are not self-contained
// types, e.g. `std::pair<UnsafeType, T>`.
if (decl->isInStdNamespace() &&
(decl->getName() == "pair" || decl->getName() == "tuple"))
return false;

if (!decl->getDefinition())
return false;

Expand Down
4 changes: 1 addition & 3 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2959,9 +2959,7 @@ namespace {
if (notInstantiated)
return nullptr;
}
if (!clangSema.isCompleteType(
decl->getLocation(),
Impl.getClangASTContext().getRecordType(decl))) {
if (!decl->getDefinition()) {
// If we got nullptr definition now it means the type is not complete.
// We don't import incomplete types.
return nullptr;
Expand Down
12 changes: 12 additions & 0 deletions test/Interop/Cxx/stdlib/Inputs/module.modulemap
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
module StdVector {
header "std-vector.h"
requires cplusplus
export *
}

module StdMap {
header "std-map.h"
requires cplusplus
export *
}

module StdOptional {
header "std-optional.h"
requires cplusplus
export *
}

module StdSet {
header "std-set.h"
requires cplusplus
export *
}

module StdPair {
header "std-pair.h"
requires cplusplus
export *
}

module MsvcUseVecIt {
Expand All @@ -32,4 +37,11 @@ module MsvcUseVecIt {
module StdUniquePtr {
header "std-unique-ptr.h"
requires cplusplus
export *
}

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

#include <functional>

using FunctionIntToInt = std::function<int(int)>;

FunctionIntToInt getIdentityFunction() {
return [](int x) { return x; };
}

bool isEmptyFunction(FunctionIntToInt f) { return !(bool)f; }

int invokeFunction(FunctionIntToInt f, int x) { return f(x); }

#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_FUNCTION_H
2 changes: 1 addition & 1 deletion test/Interop/Cxx/stdlib/Inputs/std-pair.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct __attribute__((swift_attr("import_iterator"))) Iterator {};
using PairUnsafeStructInt = std::pair<UnsafeStruct, int>;
using PairIteratorInt = std::pair<Iterator, int>;

struct HasMethodThatReturnsUnsafePair {
struct __attribute__((swift_attr("import_owned"))) HasMethodThatReturnsUnsafePair {
PairUnsafeStructInt getUnsafePair() const { return {}; }
PairIteratorInt getIteratorPair() const { return {}; }
};
29 changes: 29 additions & 0 deletions test/Interop/Cxx/stdlib/use-std-function.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop)
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=upcoming-swift)

// REQUIRES: executable_test

import StdlibUnittest
import StdFunction

var StdFunctionTestSuite = TestSuite("StdFunction")

StdFunctionTestSuite.test("init empty") {
let f = FunctionIntToInt()
expectTrue(isEmptyFunction(f))

let copied = f
expectTrue(isEmptyFunction(copied))
}

StdFunctionTestSuite.test("call") {
let f = getIdentityFunction()
expectEqual(123, f(123))
}

StdFunctionTestSuite.test("retrieve and pass back as parameter") {
let res = invokeFunction(getIdentityFunction(), 456)
expectEqual(456, res)
}

runAllTests()
11 changes: 8 additions & 3 deletions test/Interop/Cxx/stdlib/use-std-pair-typechecker.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
// RUN: %target-typecheck-verify-swift -I %S/Inputs -enable-experimental-cxx-interop
// RUN: not %target-swift-frontend %s -typecheck -I %S/Inputs -enable-experimental-cxx-interop 2>&1 | %FileCheck %s

import StdPair

let u = HasMethodThatReturnsUnsafePair()
u.getUnsafePair() // expected-error {{value of type 'HasMethodThatReturnsUnsafePair' has no member 'getUnsafePair'}}
u.getIteratorPair() // expected-error {{value of type 'HasMethodThatReturnsUnsafePair' has no member 'getIteratorPair'}}
u.getUnsafePair()
// CHECK: error: value of type 'HasMethodThatReturnsUnsafePair' has no member 'getUnsafePair'
// CHECK: note: C++ method 'getUnsafePair' may return an interior pointer

u.getIteratorPair()
// CHECK: error: value of type 'HasMethodThatReturnsUnsafePair' has no member 'getIteratorPair'
// CHECK: note: C++ method 'getIteratorPair' may return an interior pointer