Skip to content

Commit 5fd4979

Browse files
authored
Merge pull request #64918 from apple/egorzhdan/5.9-pointy-is-scary
🍒[cxx-interop] Treat un-instantiated templated types as unsafe
2 parents 8ec1efd + 1ccf19c commit 5fd4979

File tree

4 files changed

+60
-14
lines changed

4 files changed

+60
-14
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6395,7 +6395,9 @@ static bool hasIteratorAPIAttr(const clang::Decl *decl) {
63956395
static bool hasPointerInSubobjects(const clang::CXXRecordDecl *decl) {
63966396
// Probably a class template that has not yet been specialized:
63976397
if (!decl->getDefinition())
6398-
return false;
6398+
// If the definition is unknown, there is no way to determine if the type
6399+
// stores pointers. Stay on the safe side and assume that it does.
6400+
return true;
63996401

64006402
auto checkType = [](clang::QualType t) {
64016403
if (t->isPointerType())
@@ -6689,9 +6691,10 @@ bool IsSafeUseOfCxxDecl::evaluate(Evaluator &evaluator,
66896691
return false;
66906692
}
66916693

6692-
// Mark this as safe to help our diganostics down the road.
66936694
if (!cxxRecordReturnType->getDefinition()) {
6694-
return true;
6695+
// This is a templated type that has not been instantiated yet. We do
6696+
// not know if it is safe. Assume that it isn't.
6697+
return false;
66956698
}
66966699

66976700
if (!cxxRecordReturnType->hasUserDeclaredCopyConstructor() &&

test/Interop/Cxx/class/Inputs/type-classification.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,32 @@ struct HasMethodThatReturnsIteratorBox {
213213
IteratorBox getIteratorBox() const;
214214
};
215215

216+
template <typename T>
217+
struct TemplatedPointerBox {
218+
T *ptr;
219+
};
220+
221+
struct HasMethodThatReturnsTemplatedPointerBox {
222+
TemplatedPointerBox<int> getTemplatedPointerBox() const;
223+
};
224+
225+
template <typename T>
226+
struct TemplatedBox {
227+
T value;
228+
};
229+
230+
struct HasMethodThatReturnsTemplatedBox {
231+
TemplatedBox<int> getIntBox() const;
232+
TemplatedBox<int *> getIntPtrBox() const;
233+
};
234+
235+
template <typename T>
236+
struct __attribute__((swift_attr("import_iterator"))) TemplatedIterator {
237+
T idx;
238+
};
239+
240+
struct HasMethodThatReturnsTemplatedIterator {
241+
TemplatedIterator<int *> getIterator() const;
242+
};
243+
216244
#endif // TEST_INTEROP_CXX_CLASS_INPUTS_TYPE_CLASSIFICATION_H

test/Interop/Cxx/class/type-classification-module-interface.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,18 @@
3535
// CHECK: func __getIteratorBoxUnsafe() -> IteratorBox
3636
// CHECK-SKIP-UNSAFE-NOT: func __getIteratorBoxUnsafe() -> IteratorBox
3737
// CHECK: }
38+
39+
// CHECK: struct HasMethodThatReturnsTemplatedPointerBox {
40+
// CHECK: func __getTemplatedPointerBoxUnsafe() -> TemplatedPointerBox<Int32>
41+
// CHECK-SKIP-UNSAFE-NOT: func __getTemplatedPointerBoxUnsafe() -> TemplatedPointerBox<Int32>
42+
// CHECK: }
43+
44+
// CHECK: struct HasMethodThatReturnsTemplatedBox {
45+
// FIXME: This is unfortunate, we should be able to recognize that TemplatedBox<Int32> does not store any pointers as fields.
46+
// CHECK: func __getIntBoxUnsafe() -> TemplatedBox<Int32>
47+
// CHECK: func __getIntPtrBoxUnsafe()
48+
// CHECK: }
49+
50+
// CHECK: struct HasMethodThatReturnsTemplatedIterator {
51+
// CHECK: func __getIteratorUnsafe()
52+
// CHECK: }

test/Interop/Cxx/templates/Inputs/large-class-templates.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,17 @@ struct ValExpr {
2828
using type = typename E::type;
2929
E expr;
3030

31-
ValExpr<SliceExpr<E, 1>> test1() { return {SliceExpr<E, 1>{expr}}; }
32-
ValExpr<SliceExpr<E, 2>> test2() { return {SliceExpr<E, 2>{expr}}; }
33-
ValExpr<SliceExpr<E, 3>> test3() { return {SliceExpr<E, 3>{expr}}; }
34-
ValExpr<SliceExpr<E, 4>> test4() { return {SliceExpr<E, 4>{expr}}; }
35-
ValExpr<SliceExpr<E, 5>> test5() { return {SliceExpr<E, 5>{expr}}; }
36-
ValExpr<SliceExpr<E, 6>> test6() { return {SliceExpr<E, 6>{expr}}; }
37-
ValExpr<SliceExpr<E, 7>> test7() { return {SliceExpr<E, 7>{expr}}; }
38-
ValExpr<SliceExpr<E, 8>> test8() { return {SliceExpr<E, 8>{expr}}; }
39-
ValExpr<SliceExpr<E, 9>> test9() { return {SliceExpr<E, 8>{expr}}; }
40-
ValExpr<SliceExpr<E, 11>> test11() { return {SliceExpr<E, 11>{expr}}; }
41-
ValExpr<SliceExpr<E, 12>> test12() { return {SliceExpr<E, 12>{expr}}; }
31+
ValExpr<SliceExpr<E, 1>> test1() __attribute__((swift_attr("import_unsafe"))) { return {SliceExpr<E, 1>{expr}}; }
32+
ValExpr<SliceExpr<E, 2>> test2() __attribute__((swift_attr("import_unsafe"))) { return {SliceExpr<E, 2>{expr}}; }
33+
ValExpr<SliceExpr<E, 3>> test3() __attribute__((swift_attr("import_unsafe"))) { return {SliceExpr<E, 3>{expr}}; }
34+
ValExpr<SliceExpr<E, 4>> test4() __attribute__((swift_attr("import_unsafe"))) { return {SliceExpr<E, 4>{expr}}; }
35+
ValExpr<SliceExpr<E, 5>> test5() __attribute__((swift_attr("import_unsafe"))) { return {SliceExpr<E, 5>{expr}}; }
36+
ValExpr<SliceExpr<E, 6>> test6() __attribute__((swift_attr("import_unsafe"))) { return {SliceExpr<E, 6>{expr}}; }
37+
ValExpr<SliceExpr<E, 7>> test7() __attribute__((swift_attr("import_unsafe"))) { return {SliceExpr<E, 7>{expr}}; }
38+
ValExpr<SliceExpr<E, 8>> test8() __attribute__((swift_attr("import_unsafe"))) { return {SliceExpr<E, 8>{expr}}; }
39+
ValExpr<SliceExpr<E, 9>> test9() __attribute__((swift_attr("import_unsafe"))) { return {SliceExpr<E, 8>{expr}}; }
40+
ValExpr<SliceExpr<E, 11>> test11() __attribute__((swift_attr("import_unsafe"))) { return {SliceExpr<E, 11>{expr}}; }
41+
ValExpr<SliceExpr<E, 12>> test12() __attribute__((swift_attr("import_unsafe"))) { return {SliceExpr<E, 12>{expr}}; }
4242
};
4343

4444
// This class template is exponentially slow to *fully* instantiate (and the

0 commit comments

Comments
 (0)