Skip to content

Commit 6081d0e

Browse files
committed
[cxx-interop] Do not treat std::pair<UnsafeType, T> as safe
rdar://109529750
1 parent 4920e4a commit 6081d0e

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

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

6635-
if (!cxxDecl->hasUserDeclaredCopyConstructor() &&
6636-
!cxxDecl->hasUserDeclaredMoveConstructor() &&
6646+
if (!hasCustomCopyOrMoveConstructor(cxxDecl) &&
66376647
hasPointerInSubobjects(cxxDecl)) {
66386648
return CxxRecordSemanticsKind::UnsafePointerMember;
66396649
}
@@ -6721,8 +6731,7 @@ bool IsSafeUseOfCxxDecl::evaluate(Evaluator &evaluator,
67216731
return true;
67226732
}
67236733

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