Skip to content

Commit 6073432

Browse files
authored
Merge pull request #66284 from apple/egorzhdan/5.9-pair-tuple-unsafe
🍒[cxx-interop] Do not treat `std::pair<UnsafeType, T>` as safe
2 parents 72612a2 + 28d9ea8 commit 6073432

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
@@ -6566,6 +6566,17 @@ static bool hasDestroyTypeOperations(const clang::CXXRecordDecl *decl) {
65666566
return false;
65676567
}
65686568

6569+
static bool hasCustomCopyOrMoveConstructor(const clang::CXXRecordDecl *decl) {
6570+
// std::pair and std::tuple might have copy and move constructors, but that
6571+
// doesn't mean they are safe to use from Swift, e.g. std::pair<UnsafeType, T>
6572+
if (decl->isInStdNamespace() &&
6573+
(decl->getName() == "pair" || decl->getName() == "tuple")) {
6574+
return false;
6575+
}
6576+
return decl->hasUserDeclaredCopyConstructor() ||
6577+
decl->hasUserDeclaredMoveConstructor();
6578+
}
6579+
65696580
static bool isSwiftClassType(const clang::CXXRecordDecl *decl) {
65706581
// Swift type must be annotated with external_source_symbol attribute.
65716582
auto essAttr = decl->getAttr<clang::ExternalSourceSymbolAttr>();
@@ -6633,8 +6644,7 @@ CxxRecordSemantics::evaluate(Evaluator &evaluator,
66336644
return CxxRecordSemanticsKind::Iterator;
66346645
}
66356646

6636-
if (!cxxDecl->hasUserDeclaredCopyConstructor() &&
6637-
!cxxDecl->hasUserDeclaredMoveConstructor() &&
6647+
if (!hasCustomCopyOrMoveConstructor(cxxDecl) &&
66386648
hasPointerInSubobjects(cxxDecl)) {
66396649
return CxxRecordSemanticsKind::UnsafePointerMember;
66406650
}
@@ -6722,8 +6732,7 @@ bool IsSafeUseOfCxxDecl::evaluate(Evaluator &evaluator,
67226732
return true;
67236733
}
67246734

6725-
if (!cxxRecordReturnType->hasUserDeclaredCopyConstructor() &&
6726-
!cxxRecordReturnType->hasUserDeclaredMoveConstructor() &&
6735+
if (!hasCustomCopyOrMoveConstructor(cxxRecordReturnType) &&
67276736
!hasOwnedValueAttr(cxxRecordReturnType) &&
67286737
hasPointerInSubobjects(cxxRecordReturnType)) {
67296738
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)