From d61b8855e9f42f38a8e7ba528c43d450073c70d3 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 9 Oct 2023 20:02:48 -0700 Subject: [PATCH] stdlib: map `wchar_t` to `UInt16` on Windows This is an ABI breaking change for Windows. `WCHAR` on Windows is mapped to `short` (`-fshort-wchar` makes it `unsigned short`). When C++ interop is enabled, `WCHAR` will be mapped to `wchar_t` which is then mapped to `short` (or `unsigned short` if `-fshort-wchar` is specified). Correct the mapping type to get the desired behaviour. --- stdlib/public/core/CTypes.swift | 4 ++++ test/ClangImporter/Inputs/unicode/module.modulemap | 4 ++++ test/ClangImporter/Inputs/unicode/unicode.h | 6 ++++++ test/ClangImporter/unicode.swift | 10 ++++++++++ .../swift-primitive-functions-c-bridging.swift | 5 +++-- .../functions/swift-primitive-functions-execution.c | 4 ++++ .../swift-primitive-functions-cxx-bridging.swift | 5 +++-- test/stdlib/PrintInteger.swift | 12 ++++++++++++ 8 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 test/ClangImporter/Inputs/unicode/module.modulemap create mode 100644 test/ClangImporter/Inputs/unicode/unicode.h create mode 100644 test/ClangImporter/unicode.swift diff --git a/stdlib/public/core/CTypes.swift b/stdlib/public/core/CTypes.swift index 2f5a1ed41b7..c4c6f4e1e68 100644 --- a/stdlib/public/core/CTypes.swift +++ b/stdlib/public/core/CTypes.swift @@ -116,7 +116,11 @@ public typealias CLongDouble = Float80 // FIXME: Is it actually UTF-32 on Darwin? // /// The C++ 'wchar_t' type. +#if os(Windows) +public typealias CWideChar = UInt16 +#else public typealias CWideChar = Unicode.Scalar +#endif // FIXME: Swift should probably have a UTF-16 type other than UInt16. // diff --git a/test/ClangImporter/Inputs/unicode/module.modulemap b/test/ClangImporter/Inputs/unicode/module.modulemap new file mode 100644 index 00000000000..cff88fa2959 --- /dev/null +++ b/test/ClangImporter/Inputs/unicode/module.modulemap @@ -0,0 +1,4 @@ +module unicode { + header "unicode.h" + export * +} diff --git a/test/ClangImporter/Inputs/unicode/unicode.h b/test/ClangImporter/Inputs/unicode/unicode.h new file mode 100644 index 00000000000..99a21ada80f --- /dev/null +++ b/test/ClangImporter/Inputs/unicode/unicode.h @@ -0,0 +1,6 @@ + +#if !defined(__cplusplus) +typedef short wchar_t; +#endif +typedef wchar_t WCHAR; +#define UNICODE_NULL ((WCHAR)0) diff --git a/test/ClangImporter/unicode.swift b/test/ClangImporter/unicode.swift new file mode 100644 index 00000000000..a2d6bc186c6 --- /dev/null +++ b/test/ClangImporter/unicode.swift @@ -0,0 +1,10 @@ +// RUN: %swift-ide-test -target x86_64-unknown-windows-msvc -print-module -module-to-print unicode -print-interface -source-filename %s -I %S/Inputs/unicode | %FileCheck %s -check-prefix CHECK-C +// RUN: %swift-ide-test -target x86_64-unknown-windows-msvc -enable-experimental-cxx-interop -print-module -module-to-print unicode -print-interface -source-filename %s -I %S/Inputs/unicode | %FileCheck %s -check-prefix CHECK-CXX + +// REQUIRES: OS=windows-msvc + +import unicode + +// CHECK-C: typealias WCHAR = wchar_t +// CHECK-CXX: typealias WCHAR = CWideChar +// CHECK: var UNICODE_NULL: WCHAR { get } diff --git a/test/Interop/SwiftToC/functions/swift-primitive-functions-c-bridging.swift b/test/Interop/SwiftToC/functions/swift-primitive-functions-c-bridging.swift index 88718bf3963..1241ed8f89e 100644 --- a/test/Interop/SwiftToC/functions/swift-primitive-functions-c-bridging.swift +++ b/test/Interop/SwiftToC/functions/swift-primitive-functions-c-bridging.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend %s -typecheck -module-name Functions -clang-header-expose-decls=all-public -emit-clang-header-path %t/functions.h -// RUN: %FileCheck %s < %t/functions.h +// RUN: %FileCheck %s -check-prefix CHECK -check-prefix CHECK-%target-abi < %t/functions.h // RUN: %check-interop-c-header-in-clang(%t/functions.h) @@ -19,7 +19,8 @@ // CHECK-NEXT: SWIFT_EXTERN unsigned long long $s9Functions024passThroughCUnsignedLongE0ys6UInt64VADF(unsigned long long x) SWIFT_NOEXCEPT SWIFT_CALL; // CHECK-NEXT: SWIFT_EXTERN unsigned short $s9Functions25passThroughCUnsignedShortys6UInt16VADF(unsigned short x) SWIFT_NOEXCEPT SWIFT_CALL; // CHECK-NEXT: SWIFT_EXTERN unsigned char $s9Functions30passThroughCUnsignedSignedCharys5UInt8VADF(unsigned char x) SWIFT_NOEXCEPT SWIFT_CALL; -// CHECK-NEXT: SWIFT_EXTERN wchar_t $s9Functions20passThroughCWideCharys7UnicodeO6ScalarVAFF(wchar_t x) SWIFT_NOEXCEPT SWIFT_CALL; +// CHECK-SYSV-NEXT: SWIFT_EXTERN wchar_t $s9Functions20passThroughCWideCharys7UnicodeO6ScalarVAFF(wchar_t x) SWIFT_NOEXCEPT SWIFT_CALL; +// CHECK-WIN-NEXT: SWIFT_EXTERN wchar_t $s9Functions20passThroughCWideCharys6UInt16VADF(wchar_t x) SWIFT_NOEXCEPT SWIFT_CALL; // CHECK-NEXT: SWIFT_EXTERN double $s9Functions17passThroughDoubleyS2dF(double x) SWIFT_NOEXCEPT SWIFT_CALL; // CHECK-NEXT: SWIFT_EXTERN float $s9Functions16passThroughFloatyS2fF(float x) SWIFT_NOEXCEPT SWIFT_CALL; // CHECK-NEXT: SWIFT_EXTERN float $s9Functions18passThroughFloat32yS2fF(float x) SWIFT_NOEXCEPT SWIFT_CALL; diff --git a/test/Interop/SwiftToC/functions/swift-primitive-functions-execution.c b/test/Interop/SwiftToC/functions/swift-primitive-functions-execution.c index 747c64d4d19..27e1c625587 100644 --- a/test/Interop/SwiftToC/functions/swift-primitive-functions-execution.c +++ b/test/Interop/SwiftToC/functions/swift-primitive-functions-execution.c @@ -22,7 +22,11 @@ int main() { // passThroughCChar VERIFY_PASSTHROUGH_VALUE($s9Functions16passThroughCCharys4Int8VADF, 'a'); // passThroughCWideChar +#if defined(_WIN32) + VERIFY_PASSTHROUGH_VALUE($s9Functions20passThroughCWideCharys6UInt16VADF, 'a'); +#else VERIFY_PASSTHROUGH_VALUE($s9Functions20passThroughCWideCharys7UnicodeO6ScalarVAFF, 'a'); +#endif // passThroughCChar16 VERIFY_PASSTHROUGH_VALUE($s9Functions18passThroughCChar16ys6UInt16VADF, 0xFE1); // passThroughCChar32 diff --git a/test/Interop/SwiftToCxx/functions/swift-primitive-functions-cxx-bridging.swift b/test/Interop/SwiftToCxx/functions/swift-primitive-functions-cxx-bridging.swift index 33e94f78c4a..b7a5d3622a3 100644 --- a/test/Interop/SwiftToCxx/functions/swift-primitive-functions-cxx-bridging.swift +++ b/test/Interop/SwiftToCxx/functions/swift-primitive-functions-cxx-bridging.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) // RUN: %target-swift-frontend %s -typecheck -module-name Functions -clang-header-expose-decls=all-public -emit-clang-header-path %t/functions.h -// RUN: %FileCheck %s < %t/functions.h +// RUN: %FileCheck %s -check-prefix CHECK -check-prefix CHECK-%target-abi < %t/functions.h // RUN: %check-interop-cxx-header-in-clang(%t/functions.h) @@ -67,7 +67,8 @@ // CHECK-NEXT: } // CHECK: SWIFT_INLINE_THUNK wchar_t passThroughCWideChar(wchar_t x) noexcept SWIFT_SYMBOL({{.*}}) SWIFT_WARN_UNUSED_RESULT { -// CHECK-NEXT: return _impl::$s9Functions20passThroughCWideCharys7UnicodeO6ScalarVAFF(x); +// CHECK-SYSV: return _impl::$s9Functions20passThroughCWideCharys7UnicodeO6ScalarVAFF(x); +// CHECK-WIN: return _impl::$s9Functions20passThroughCWideCharys6UInt16VADF(x); // CHECK-NEXT: } // CHECK: SWIFT_INLINE_THUNK double passThroughDouble(double x) noexcept SWIFT_SYMBOL({{.*}}) SWIFT_WARN_UNUSED_RESULT { diff --git a/test/stdlib/PrintInteger.swift b/test/stdlib/PrintInteger.swift index 01f3418c0f8..6475067642e 100644 --- a/test/stdlib/PrintInteger.swift +++ b/test/stdlib/PrintInteger.swift @@ -34,7 +34,11 @@ PrintTests.test("CustomStringConvertible") { hasDescription(CInt(42)) hasDescription(CLong(42)) hasDescription(CLongLong(42)) +#if os(Windows) + hasDescription(CWideChar(exactly: 42)!) +#else hasDescription(CWideChar(42)!) +#endif hasDescription(CChar16(42)) hasDescription(CChar32(42)!) } @@ -51,7 +55,11 @@ PrintTests.test("Printable") { expectPrinted("42", CInt(42)) expectPrinted("42", CLong(42)) expectPrinted("42", CLongLong(42)) +#if os(Windows) + expectPrinted("42", CWideChar(exactly: 42)!) +#else expectPrinted("*", CWideChar(42)!) +#endif expectPrinted("42", CChar16(42)) expectPrinted("*", CChar32(42)!) @@ -142,7 +150,11 @@ PrintTests.test("Printable") { expectPrinted("42", CLong(42)) expectPrinted("42", CLongLong(42)) +#if os(Windows) + expectPrinted("42", CWideChar(exactly: 42)!) +#else expectPrinted("*", CWideChar(42)!) +#endif expectPrinted("42", CChar16(42)) expectPrinted("*", CChar32(42)!) }