Skip to content

Commit c179e23

Browse files
committed
[interop][SwiftToCxx] add static_assert type checking for generic types in pre-C++20 mode
1 parent a66cc52 commit c179e23

File tree

5 files changed

+41
-0
lines changed

5 files changed

+41
-0
lines changed

lib/PrintAsClang/PrintClangValueType.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ void ClangValueTypePrinter::printValueTypeDecl(
241241
ClangSyntaxPrinter(os).printBaseName(typeDecl);
242242
os << " final {\n";
243243
os << "public:\n";
244+
if (genericSignature)
245+
ClangSyntaxPrinter(os).printGenericSignatureInnerStaticAsserts(
246+
*genericSignature);
244247

245248
// Print out the destructor.
246249
os << " inline ~";
@@ -373,6 +376,9 @@ void ClangValueTypePrinter::printValueTypeDecl(
373376
printCxxImplClassName(os, typeDecl);
374377
os << " {\n";
375378
os << "public:\n";
379+
if (genericSignature)
380+
ClangSyntaxPrinter(os).printGenericSignatureInnerStaticAsserts(
381+
*genericSignature);
376382

377383
os << " static inline char * _Nonnull getOpaquePointer(";
378384
printCxxTypeName(os, typeDecl, moduleContext);

test/Interop/SwiftToCxx/generics/generic-enum-in-cxx.swift

+3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ public func inoutConcreteOpt(_ x: inout GenericOpt<UInt16>) {
109109
// CHECK-NEXT: #endif
110110
// CHECK-NEXT: class GenericOpt final {
111111
// CHECK-NEXT: public:
112+
// CHECK-NEXT: #ifndef __cpp_concepts
113+
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
114+
// CHECK-NEXT: #endif
112115
// CHECK-NEXT: inline ~GenericOpt() {
113116
// CHECK-NEXT: auto metadata = _impl::$s8Generics10GenericOptOMa(0, swift::TypeMetadataTrait<T_0_0>::getTypeMetadata());
114117
// CHECK-NEXT: auto *vwTableAddr = reinterpret_cast<swift::_impl::ValueWitnessTable **>(metadata._0) - 1;

test/Interop/SwiftToCxx/generics/generic-struct-in-cxx.swift

+8
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ public func inoutConcretePair(_ x: UInt16, _ y: inout GenericPair<UInt16, UInt16
222222
// CHECK-NEXT: #endif
223223
// CHECK-NEXT: class GenericPair final {
224224
// CHECK-NEXT: public:
225+
// CHECK-NEXT: #ifndef __cpp_concepts
226+
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
227+
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_1>, "type cannot be used in a Swift generic context");
228+
// CHECK-NEXT: #endif
225229
// CHECK-NEXT: inline ~GenericPair() {
226230
// CHECK-NEXT: auto metadata = _impl::$s8Generics11GenericPairVMa(0, swift::TypeMetadataTrait<T_0_0>::getTypeMetadata(), swift::TypeMetadataTrait<T_0_1>::getTypeMetadata());
227231

@@ -235,6 +239,10 @@ public func inoutConcretePair(_ x: UInt16, _ y: inout GenericPair<UInt16, UInt16
235239
// CHECK-NEXT: #endif
236240
// CHECK-NEXT: class _impl_GenericPair {
237241
// CHECK-NEXT: public:
242+
// CHECK-NEXT: #ifndef __cpp_concepts
243+
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
244+
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_1>, "type cannot be used in a Swift generic context");
245+
// CHECK-NEXT: #endif
238246
// CHECK-NEXT: static inline char * _Nonnull getOpaquePointer(GenericPair<T_0_0, T_0_1> &object) { return object._getOpaquePointer(); }
239247
// CHECK-NEXT: static inline const char * _Nonnull getOpaquePointer(const GenericPair<T_0_0, T_0_1> &object) { return object._getOpaquePointer(); }
240248
// CHECK-NEXT: template<class T>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %target-swift-frontend %S/generic-struct-in-cxx.swift -typecheck -module-name Structs -clang-header-expose-decls=all-public -emit-clang-header-path %t/structs.h
4+
5+
// RUN: %target-interop-build-clangxx -std=gnu++20 -c %s -I %t -o /dev/null -DUSE_TYPE=int
6+
// RUN: %target-interop-build-clangxx -std=gnu++17 -c %s -I %t -o /dev/null -DUSE_TYPE=int
7+
// RUN: not %target-interop-build-clangxx -std=gnu++20 -c %s -I %t -o /dev/null -DUSE_TYPE=CxxStruct
8+
// RUN: not %target-interop-build-clangxx -std=gnu++17 -c %s -I %t -o /dev/null -DUSE_TYPE=CxxStruct 2>&1 | %FileCheck -check-prefix=STATIC_ASSERT_ERROR %s
9+
10+
#include "structs.h"
11+
12+
struct CxxStruct { int x = 0; };
13+
14+
bool test(Structs::GenericPair<USE_TYPE, USE_TYPE> &val) {
15+
return sizeof(val) > 4;
16+
}
17+
18+
// STATIC_ASSERT_ERROR: type cannot be used in a Swift generic context

test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
// CHECK-NEXT: #endif
2929
// CHECK-NEXT: class Array final {
3030
// CHECK-NEXT: public:
31+
// CHECK-NEXT: #ifndef __cpp_concepts
32+
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
33+
// CHECK-NEXT: #endif
3134
// CHECK-NEXT: inline ~Array() {
3235
// CHECK: }
3336
// CHECK-NEXT: inline Array(const Array &other) {
@@ -49,6 +52,9 @@
4952
// CHECK-NEXT: #endif
5053
// CHECK-NEXT: class Optional final {
5154
// CHECK-NEXT: public:
55+
// CHECK-NEXT: #ifndef __cpp_concepts
56+
// CHECK-NEXT: static_assert(swift::isUsableInGenericContext<T_0_0>, "type cannot be used in a Swift generic context");
57+
// CHECK-NEXT: #endif
5258
// CHECK-NEXT: inline ~Optional() {
5359
// CHECK: }
5460
// CHECK-NEXT: inline Optional(const Optional &other) {

0 commit comments

Comments
 (0)