Skip to content

Commit 2061640

Browse files
authored
Merge pull request #70772 from apple/egorzhdan/std-function-initial-tests
[cxx-interop] Initial tests for `std::function` usage
2 parents 166d059 + a61d933 commit 2061640

File tree

7 files changed

+74
-13
lines changed

7 files changed

+74
-13
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7390,12 +7390,6 @@ static bool hasDestroyTypeOperations(const clang::CXXRecordDecl *decl) {
73907390
}
73917391

73927392
static bool hasCustomCopyOrMoveConstructor(const clang::CXXRecordDecl *decl) {
7393-
// std::pair and std::tuple might have copy and move constructors, but that
7394-
// doesn't mean they are safe to use from Swift, e.g. std::pair<UnsafeType, T>
7395-
if (decl->isInStdNamespace() &&
7396-
(decl->getName() == "pair" || decl->getName() == "tuple")) {
7397-
return false;
7398-
}
73997393
return decl->hasUserDeclaredCopyConstructor() ||
74007394
decl->hasUserDeclaredMoveConstructor();
74017395
}
@@ -7511,6 +7505,13 @@ CxxRecordAsSwiftType::evaluate(Evaluator &evaluator,
75117505
}
75127506

75137507
bool anySubobjectsSelfContained(const clang::CXXRecordDecl *decl) {
7508+
// std::pair and std::tuple might have copy and move constructors, or base
7509+
// classes with copy and move constructors, but they are not self-contained
7510+
// types, e.g. `std::pair<UnsafeType, T>`.
7511+
if (decl->isInStdNamespace() &&
7512+
(decl->getName() == "pair" || decl->getName() == "tuple"))
7513+
return false;
7514+
75147515
if (!decl->getDefinition())
75157516
return false;
75167517

lib/ClangImporter/ImportDecl.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2959,9 +2959,7 @@ namespace {
29592959
if (notInstantiated)
29602960
return nullptr;
29612961
}
2962-
if (!clangSema.isCompleteType(
2963-
decl->getLocation(),
2964-
Impl.getClangASTContext().getRecordType(decl))) {
2962+
if (!decl->getDefinition()) {
29652963
// If we got nullptr definition now it means the type is not complete.
29662964
// We don't import incomplete types.
29672965
return nullptr;

test/Interop/Cxx/stdlib/Inputs/module.modulemap

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
module StdVector {
22
header "std-vector.h"
33
requires cplusplus
4+
export *
45
}
56

67
module StdMap {
78
header "std-map.h"
89
requires cplusplus
10+
export *
911
}
1012

1113
module StdOptional {
1214
header "std-optional.h"
1315
requires cplusplus
16+
export *
1417
}
1518

1619
module StdSet {
1720
header "std-set.h"
1821
requires cplusplus
22+
export *
1923
}
2024

2125
module StdPair {
2226
header "std-pair.h"
2327
requires cplusplus
28+
export *
2429
}
2530

2631
module MsvcUseVecIt {
@@ -32,4 +37,11 @@ module MsvcUseVecIt {
3237
module StdUniquePtr {
3338
header "std-unique-ptr.h"
3439
requires cplusplus
40+
export *
41+
}
42+
43+
module StdFunction {
44+
header "std-function.h"
45+
requires cplusplus
46+
export *
3547
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef TEST_INTEROP_CXX_STDLIB_INPUTS_STD_FUNCTION_H
2+
#define TEST_INTEROP_CXX_STDLIB_INPUTS_STD_FUNCTION_H
3+
4+
#include <functional>
5+
6+
using FunctionIntToInt = std::function<int(int)>;
7+
8+
FunctionIntToInt getIdentityFunction() {
9+
return [](int x) { return x; };
10+
}
11+
12+
bool isEmptyFunction(FunctionIntToInt f) { return !(bool)f; }
13+
14+
int invokeFunction(FunctionIntToInt f, int x) { return f(x); }
15+
16+
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_FUNCTION_H

test/Interop/Cxx/stdlib/Inputs/std-pair.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ struct __attribute__((swift_attr("import_iterator"))) Iterator {};
3535
using PairUnsafeStructInt = std::pair<UnsafeStruct, int>;
3636
using PairIteratorInt = std::pair<Iterator, int>;
3737

38-
struct HasMethodThatReturnsUnsafePair {
38+
struct __attribute__((swift_attr("import_owned"))) HasMethodThatReturnsUnsafePair {
3939
PairUnsafeStructInt getUnsafePair() const { return {}; }
4040
PairIteratorInt getIteratorPair() const { return {}; }
4141
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop)
2+
// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=upcoming-swift)
3+
4+
// REQUIRES: executable_test
5+
6+
import StdlibUnittest
7+
import StdFunction
8+
9+
var StdFunctionTestSuite = TestSuite("StdFunction")
10+
11+
StdFunctionTestSuite.test("init empty") {
12+
let f = FunctionIntToInt()
13+
expectTrue(isEmptyFunction(f))
14+
15+
let copied = f
16+
expectTrue(isEmptyFunction(copied))
17+
}
18+
19+
StdFunctionTestSuite.test("call") {
20+
let f = getIdentityFunction()
21+
expectEqual(123, f(123))
22+
}
23+
24+
StdFunctionTestSuite.test("retrieve and pass back as parameter") {
25+
let res = invokeFunction(getIdentityFunction(), 456)
26+
expectEqual(456, res)
27+
}
28+
29+
runAllTests()
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
// RUN: %target-typecheck-verify-swift -I %S/Inputs -enable-experimental-cxx-interop
1+
// RUN: not %target-swift-frontend %s -typecheck -I %S/Inputs -enable-experimental-cxx-interop 2>&1 | %FileCheck %s
22

33
import StdPair
44

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

0 commit comments

Comments
 (0)