Skip to content

Commit 630a7fc

Browse files
authored
Merge pull request #66169 from apple/egorzhdan/pair-tuple-unsafe
[cxx-interop] Do not treat `std::pair<UnsafeType, T>` as safe
2 parents e476b22 + f277158 commit 630a7fc

File tree

3 files changed

+35
-4
lines changed

3 files changed

+35
-4
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6574,6 +6574,17 @@ static bool hasDestroyTypeOperations(const clang::CXXRecordDecl *decl) {
65746574
return false;
65756575
}
65766576

6577+
static bool hasCustomCopyOrMoveConstructor(const clang::CXXRecordDecl *decl) {
6578+
// std::pair and std::tuple might have copy and move constructors, but that
6579+
// doesn't mean they are safe to use from Swift, e.g. std::pair<UnsafeType, T>
6580+
if (decl->isInStdNamespace() &&
6581+
(decl->getName() == "pair" || decl->getName() == "tuple")) {
6582+
return false;
6583+
}
6584+
return decl->hasUserDeclaredCopyConstructor() ||
6585+
decl->hasUserDeclaredMoveConstructor();
6586+
}
6587+
65776588
static bool isSwiftClassType(const clang::CXXRecordDecl *decl) {
65786589
// Swift type must be annotated with external_source_symbol attribute.
65796590
auto essAttr = decl->getAttr<clang::ExternalSourceSymbolAttr>();
@@ -6641,8 +6652,7 @@ CxxRecordSemantics::evaluate(Evaluator &evaluator,
66416652
return CxxRecordSemanticsKind::Iterator;
66426653
}
66436654

6644-
if (!cxxDecl->hasUserDeclaredCopyConstructor() &&
6645-
!cxxDecl->hasUserDeclaredMoveConstructor() &&
6655+
if (!hasCustomCopyOrMoveConstructor(cxxDecl) &&
66466656
hasPointerInSubobjects(cxxDecl)) {
66476657
return CxxRecordSemanticsKind::UnsafePointerMember;
66486658
}
@@ -6730,8 +6740,7 @@ bool IsSafeUseOfCxxDecl::evaluate(Evaluator &evaluator,
67306740
return true;
67316741
}
67326742

6733-
if (!cxxRecordReturnType->hasUserDeclaredCopyConstructor() &&
6734-
!cxxRecordReturnType->hasUserDeclaredMoveConstructor() &&
6743+
if (!hasCustomCopyOrMoveConstructor(cxxRecordReturnType) &&
67356744
!hasOwnedValueAttr(cxxRecordReturnType) &&
67366745
hasPointerInSubobjects(cxxRecordReturnType)) {
67376746
return false;

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,17 @@ using PairStructInt = std::pair<StructInPair, int>;
2323
inline PairStructInt getPairStructInt(int x) {
2424
return { { x * 2, -x}, x };
2525
}
26+
27+
struct UnsafeStruct {
28+
int *ptr;
29+
};
30+
31+
struct __attribute__((swift_attr("import_iterator"))) Iterator {};
32+
33+
using PairUnsafeStructInt = std::pair<UnsafeStruct, int>;
34+
using PairIteratorInt = std::pair<Iterator, int>;
35+
36+
struct HasMethodThatReturnsUnsafePair {
37+
PairUnsafeStructInt getUnsafePair() const { return {}; }
38+
PairIteratorInt getIteratorPair() const { return {}; }
39+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-typecheck-verify-swift -I %S/Inputs -enable-experimental-cxx-interop
2+
// REQUIRES: OS=macosx || OS=linux-gnu
3+
4+
import StdPair
5+
6+
let u = HasMethodThatReturnsUnsafePair()
7+
u.getUnsafePair() // expected-error {{value of type 'HasMethodThatReturnsUnsafePair' has no member 'getUnsafePair'}}
8+
u.getIteratorPair() // expected-error {{value of type 'HasMethodThatReturnsUnsafePair' has no member 'getIteratorPair'}}

0 commit comments

Comments
 (0)