diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index c019ea5d60231..ed5f2c8118cd3 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -1108,6 +1108,9 @@ class alignas(1 << TypeAlignInBits) TypeBase /// Check if this is a std.string type from C++. bool isCxxString(); + /// Check if this is the type Unicode.Scalar from the Swift standard library. + bool isUnicodeScalar(); + /// Check if this type is known to represent key paths. bool isKnownKeyPathType(); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1cb25e0025c7a..52fb2ceb7345e 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1307,6 +1307,25 @@ bool TypeBase::isCxxString() { ctx.Id_basic_string.is(clangDecl->getName()); } +bool TypeBase::isUnicodeScalar() { + if (!is()) + return false; + const auto *structType = castTo(); + if (!structType->getDecl()->getName().is("Scalar")) + return false; + + Type parent = structType->getParent(); + if (!parent->is()) + return false; + const auto enumDecl = parent->castTo()->getDecl(); + if (!enumDecl->getName().is("Unicode")) + return false; + const auto *parentDC = enumDecl->getDeclContext(); + if (!parentDC->isModuleScopeContext() && parentDC->getParentModule()->isStdlibModule()) + return false; + return true; +} + bool TypeBase::isKnownKeyPathType() { return isKeyPath() || isWritableKeyPath() || isReferenceWritableKeyPath() || isPartialKeyPath() || isAnyKeyPath(); diff --git a/lib/ClangImporter/ClangIncludePaths.cpp b/lib/ClangImporter/ClangIncludePaths.cpp index 13fb11e164f96..f8289e1e8e17e 100644 --- a/lib/ClangImporter/ClangIncludePaths.cpp +++ b/lib/ClangImporter/ClangIncludePaths.cpp @@ -416,7 +416,21 @@ static void getLibStdCxxFileMapping( "bits/unique_lock.h", "bits/unique_ptr.h", "bits/unordered_map.h", "bits/unordered_set.h", "bits/uses_allocator.h", "bits/uses_allocator_args.h", "bits/valarray_after.h", - "bits/valarray_array.h", "bits/valarray_before.h"}; + "bits/valarray_array.h", "bits/valarray_before.h", "bits/version.h", + // C++20 and newer: + "barrier", + "compare", + "concepts", + "format", + "latch", + "numbers", + "ranges", + "semaphore", + "source_location", + "span", + "stop_token", + "syncstream", + }; std::string additionalHeaderDirectives; llvm::raw_string_ostream os(additionalHeaderDirectives); os << contents.substr(0, headerInjectionPoint); diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 13750fee1c517..0627a8e5ed4ee 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -4675,8 +4675,14 @@ namespace { // Do not attempts to import ObjCBool values, for similar reasons. bool isObjCBool = (type && type->isObjCBool()) || (type && synthesizer.isObjCBool(type)); - - if (type && !isCGFloat && !isObjCBool) { + // Do not attempts to import CWideChar (wchar_t) values. CWideChar is + // a typealias for Unicode.Scalar, which does not + // implement _ExpressibleByBuiltinIntegerLiteral. + // FIXME: import using _ExpressibleByUnicodeScalarLiteral. + bool isUnicodeScalar = (type && type->isUnicodeScalar()) || + (type && synthesizer.isUnicodeScalar(type)); + + if (type && !isCGFloat && !isObjCBool && !isUnicodeScalar) { auto convertKind = ConstantConvertKind::None; // Request conversions on enums, and swift_wrapper((enum/struct)) // types diff --git a/lib/ClangImporter/SwiftDeclSynthesizer.cpp b/lib/ClangImporter/SwiftDeclSynthesizer.cpp index 1059413ada45e..751a1e6d202a2 100644 --- a/lib/ClangImporter/SwiftDeclSynthesizer.cpp +++ b/lib/ClangImporter/SwiftDeclSynthesizer.cpp @@ -219,6 +219,16 @@ bool SwiftDeclSynthesizer::isObjCBool(Type type) { return importTy->isObjCBool(); } +bool SwiftDeclSynthesizer::isUnicodeScalar(Type type) { + auto found = ImporterImpl.RawTypes.find(type->getAnyNominal()); + if (found == ImporterImpl.RawTypes.end()) { + return false; + } + + Type importTy = found->second; + return importTy->isUnicodeScalar(); +} + ValueDecl *SwiftDeclSynthesizer::createConstant(Identifier name, DeclContext *dc, Type type, const clang::APValue &value, diff --git a/lib/ClangImporter/SwiftDeclSynthesizer.h b/lib/ClangImporter/SwiftDeclSynthesizer.h index 813308bb95817..8ca3eaec128e4 100644 --- a/lib/ClangImporter/SwiftDeclSynthesizer.h +++ b/lib/ClangImporter/SwiftDeclSynthesizer.h @@ -356,6 +356,8 @@ class SwiftDeclSynthesizer { bool isObjCBool(Type type); + bool isUnicodeScalar(Type type); + private: Type getConstantLiteralType(Type type, ConstantConvertKind convertKind); diff --git a/stdlib/public/Cxx/libstdcxx/libstdcxx.modulemap b/stdlib/public/Cxx/libstdcxx/libstdcxx.modulemap index aec95fcd5523c..4627ffd22307b 100644 --- a/stdlib/public/Cxx/libstdcxx/libstdcxx.modulemap +++ b/stdlib/public/Cxx/libstdcxx/libstdcxx.modulemap @@ -42,7 +42,6 @@ module std { header "ostream" header "queue" header "set" - header "span" header "sstream" header "stack" header "stdexcept" diff --git a/test/Interop/C/chars/Inputs/import-cchar-types.h b/test/Interop/C/chars/Inputs/import-cchar-types.h index 466aafd567997..6c3600d2b5ced 100644 --- a/test/Interop/C/chars/Inputs/import-cchar-types.h +++ b/test/Interop/C/chars/Inputs/import-cchar-types.h @@ -6,6 +6,10 @@ extern char a_char; extern wchar_t a_wchar; +// This case is a regression test for a crash when importing constant initializers for wchar_t, +// since Unicode.Scalar cannot be initialized with integer literals. +const wchar_t an_initialized_wchar = 2; + #if __cplusplus extern char8_t small_char; #endif diff --git a/test/Interop/C/chars/import-cchar-types.swift b/test/Interop/C/chars/import-cchar-types.swift index b5afdaf20fb9d..9ed50bd7d83c4 100644 --- a/test/Interop/C/chars/import-cchar-types.swift +++ b/test/Interop/C/chars/import-cchar-types.swift @@ -3,5 +3,6 @@ // CHECK: var a_char: CChar // CHECK: var a_wchar: wchar_t +// CHECK: var an_initialized_wchar: wchar_t { get } // CHECK-CXX: var small_char: UInt8