Skip to content

Commit 5519be8

Browse files
committed
Move span to conditional header in libstdc++ module map
`span` is not available in all versions of libstd++, so make it a conditional header. Also adds other missing c++20 headers. Fixing this triggered an assert when importing a constant initialized `wchar_t` variable, so that is also fixed. The reason is that `wchar_t` is mapped to `Unicode.Scalar`, which cannot be directly initialized by integer literals in Swift, triggering an assert when looking up the protocol conformance for `_ExpressibleByBuiltinIntegerLiteral`. rdar://162074714
1 parent 876fd51 commit 5519be8

File tree

9 files changed

+62
-4
lines changed

9 files changed

+62
-4
lines changed

include/swift/AST/Types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,9 @@ class alignas(1 << TypeAlignInBits) TypeBase
11081108
/// Check if this is a std.string type from C++.
11091109
bool isCxxString();
11101110

1111+
/// Check if this is the type Unicode.Scalar from the Swift standard library.
1112+
bool isUnicodeScalar();
1113+
11111114
/// Check if this type is known to represent key paths.
11121115
bool isKnownKeyPathType();
11131116

lib/AST/Type.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,25 @@ bool TypeBase::isCxxString() {
13071307
ctx.Id_basic_string.is(clangDecl->getName());
13081308
}
13091309

1310+
bool TypeBase::isUnicodeScalar() {
1311+
if (!is<StructType>())
1312+
return false;
1313+
const auto *structType = castTo<StructType>();
1314+
if (!structType->getDecl()->getName().is("Scalar"))
1315+
return false;
1316+
1317+
Type parent = structType->getParent();
1318+
if (!parent->is<EnumType>())
1319+
return false;
1320+
const auto enumDecl = parent->castTo<EnumType>()->getDecl();
1321+
if (!enumDecl->getName().is("Unicode"))
1322+
return false;
1323+
const auto *parentDC = enumDecl->getDeclContext();
1324+
if (!parentDC->isModuleScopeContext() && parentDC->getParentModule()->isStdlibModule())
1325+
return false;
1326+
return true;
1327+
}
1328+
13101329
bool TypeBase::isKnownKeyPathType() {
13111330
return isKeyPath() || isWritableKeyPath() || isReferenceWritableKeyPath() ||
13121331
isPartialKeyPath() || isAnyKeyPath();

lib/ClangImporter/ClangIncludePaths.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,21 @@ static void getLibStdCxxFileMapping(
416416
"bits/unique_lock.h", "bits/unique_ptr.h", "bits/unordered_map.h",
417417
"bits/unordered_set.h", "bits/uses_allocator.h",
418418
"bits/uses_allocator_args.h", "bits/valarray_after.h",
419-
"bits/valarray_array.h", "bits/valarray_before.h"};
419+
"bits/valarray_array.h", "bits/valarray_before.h", "bits/version.h",
420+
// C++20 and newer:
421+
"barrier",
422+
"compare",
423+
"concepts",
424+
"format",
425+
"latch",
426+
"numbers",
427+
"ranges",
428+
"semaphore",
429+
"source_location",
430+
"span",
431+
"stop_token",
432+
"syncstream",
433+
};
420434
std::string additionalHeaderDirectives;
421435
llvm::raw_string_ostream os(additionalHeaderDirectives);
422436
os << contents.substr(0, headerInjectionPoint);

lib/ClangImporter/ImportDecl.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4675,8 +4675,14 @@ namespace {
46754675
// Do not attempts to import ObjCBool values, for similar reasons.
46764676
bool isObjCBool = (type && type->isObjCBool()) ||
46774677
(type && synthesizer.isObjCBool(type));
4678-
4679-
if (type && !isCGFloat && !isObjCBool) {
4678+
// Do not attempts to import CWideChar (wchar_t) values. CWideChar is
4679+
// a typealias for Unicode.Scalar, which does not
4680+
// implement _ExpressibleByBuiltinIntegerLiteral.
4681+
// FIXME: import using _ExpressibleByUnicodeScalarLiteral.
4682+
bool isUnicodeScalar = (type && type->isUnicodeScalar()) ||
4683+
(type && synthesizer.isUnicodeScalar(type));
4684+
4685+
if (type && !isCGFloat && !isObjCBool && !isUnicodeScalar) {
46804686
auto convertKind = ConstantConvertKind::None;
46814687
// Request conversions on enums, and swift_wrapper((enum/struct))
46824688
// types

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,16 @@ bool SwiftDeclSynthesizer::isObjCBool(Type type) {
219219
return importTy->isObjCBool();
220220
}
221221

222+
bool SwiftDeclSynthesizer::isUnicodeScalar(Type type) {
223+
auto found = ImporterImpl.RawTypes.find(type->getAnyNominal());
224+
if (found == ImporterImpl.RawTypes.end()) {
225+
return false;
226+
}
227+
228+
Type importTy = found->second;
229+
return importTy->isUnicodeScalar();
230+
}
231+
222232
ValueDecl *SwiftDeclSynthesizer::createConstant(Identifier name,
223233
DeclContext *dc, Type type,
224234
const clang::APValue &value,

lib/ClangImporter/SwiftDeclSynthesizer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,8 @@ class SwiftDeclSynthesizer {
356356

357357
bool isObjCBool(Type type);
358358

359+
bool isUnicodeScalar(Type type);
360+
359361
private:
360362
Type getConstantLiteralType(Type type, ConstantConvertKind convertKind);
361363

stdlib/public/Cxx/libstdcxx/libstdcxx.modulemap

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ module std {
4242
header "ostream"
4343
header "queue"
4444
header "set"
45-
header "span"
4645
header "sstream"
4746
header "stack"
4847
header "stdexcept"

test/Interop/C/chars/Inputs/import-cchar-types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
extern char a_char;
77
extern wchar_t a_wchar;
88

9+
// This case is a regression test for a crash when importing constant initializers for wchar_t,
10+
// since Unicode.Scalar cannot be initialized with integer literals.
11+
const wchar_t an_initialized_wchar = 2;
12+
913
#if __cplusplus
1014
extern char8_t small_char;
1115
#endif

test/Interop/C/chars/import-cchar-types.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33

44
// CHECK: var a_char: CChar
55
// CHECK: var a_wchar: wchar_t
6+
// CHECK: var an_initialized_wchar: wchar_t { get }
67

78
// CHECK-CXX: var small_char: UInt8

0 commit comments

Comments
 (0)