Skip to content

Commit 09edc47

Browse files
authored
Merge pull request #83550 from xymus/scalar-printing
PrintAsClang: Use proper types and look through typealiases in PrimitiveTypeMapping
2 parents 7acecdc + 6e8857a commit 09edc47

File tree

3 files changed

+118
-39
lines changed

3 files changed

+118
-39
lines changed

lib/PrintAsClang/PrimitiveTypeMapping.cpp

Lines changed: 95 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,82 @@
1919

2020
using namespace swift;
2121

22+
/// Find the implementation of the named type in the named module if loaded.
23+
static TypeDecl *findTypeInModuleByName(ASTContext &ctx,
24+
Identifier moduleName,
25+
Identifier typeName) {
26+
auto module = ctx.getLoadedModule(moduleName);
27+
if (!module)
28+
return nullptr;
29+
30+
// Find all of the declarations with this name in the Swift module.
31+
SmallVector<ValueDecl *, 1> results;
32+
module->lookupValue(typeName, NLKind::UnqualifiedLookup, results);
33+
assert(results.size() <= 1 &&
34+
"Expected at most one match for a primitive type");
35+
for (auto result : results) {
36+
if (auto nominal = dyn_cast<NominalTypeDecl>(result))
37+
return nominal;
38+
39+
if (auto typealias = dyn_cast<TypeAliasDecl>(result))
40+
return typealias;
41+
}
42+
43+
return nullptr;
44+
}
45+
2246
void PrimitiveTypeMapping::initialize(ASTContext &ctx) {
2347
assert(mappedTypeNames.empty() && "expected empty type map");
48+
49+
auto addMappedType = [&](Identifier moduleName, Identifier typeName,
50+
FullClangTypeInfo info,
51+
bool applyToUnderlying = true) {
52+
auto decl = findTypeInModuleByName(ctx, moduleName, typeName);
53+
if (!decl)
54+
return;
55+
56+
// Always map a direct definition match. Either the nominal decl or the
57+
// typealias itself.
58+
mappedTypeNames[decl] = info;
59+
60+
// If the underlying type of a typealias doesn't have a type, set it here.
61+
// This aims to reproduce the typealias behavior from BuiltinMappedTypes.
62+
auto typealias = dyn_cast<TypeAliasDecl>(decl);
63+
if (applyToUnderlying && typealias) {
64+
auto underlying = typealias->getDeclaredInterfaceType()->getAnyNominal();
65+
if (underlying && !mappedTypeNames.contains(underlying))
66+
mappedTypeNames[underlying] = info;
67+
}
68+
};
69+
70+
// Map stdlib types.
2471
#define MAP(SWIFT_NAME, CLANG_REPR, NEEDS_NULLABILITY) \
25-
mappedTypeNames[{ctx.StdlibModuleName, ctx.getIdentifier(#SWIFT_NAME)}] = { \
26-
CLANG_REPR, std::optional<StringRef>(CLANG_REPR), \
27-
std::optional<StringRef>(CLANG_REPR), NEEDS_NULLABILITY}
72+
addMappedType(ctx.StdlibModuleName, \
73+
ctx.getIdentifier(#SWIFT_NAME), \
74+
{CLANG_REPR, std::optional<StringRef>(CLANG_REPR), \
75+
std::optional<StringRef>(CLANG_REPR), NEEDS_NULLABILITY})
2876
#define MAP_C(SWIFT_NAME, OBJC_REPR, C_REPR, NEEDS_NULLABILITY) \
29-
mappedTypeNames[{ctx.StdlibModuleName, ctx.getIdentifier(#SWIFT_NAME)}] = { \
30-
OBJC_REPR, std::optional<StringRef>(C_REPR), \
31-
std::optional<StringRef>(C_REPR), NEEDS_NULLABILITY}
77+
addMappedType(ctx.StdlibModuleName, \
78+
ctx.getIdentifier(#SWIFT_NAME), \
79+
{OBJC_REPR, std::optional<StringRef>(C_REPR), \
80+
std::optional<StringRef>(C_REPR), NEEDS_NULLABILITY})
3281
#define MAP_CXX(SWIFT_NAME, OBJC_REPR, C_REPR, CXX_REPR, NEEDS_NULLABILITY) \
33-
mappedTypeNames[{ctx.StdlibModuleName, ctx.getIdentifier(#SWIFT_NAME)}] = { \
34-
OBJC_REPR, std::optional<StringRef>(C_REPR), \
35-
std::optional<StringRef>(CXX_REPR), NEEDS_NULLABILITY}
82+
addMappedType(ctx.StdlibModuleName, \
83+
ctx.getIdentifier(#SWIFT_NAME), \
84+
{OBJC_REPR, std::optional<StringRef>(C_REPR), \
85+
std::optional<StringRef>(CXX_REPR), NEEDS_NULLABILITY})
3686

3787
MAP(CBool, "bool", false);
3888

3989
MAP(CChar, "char", false);
40-
MAP(CWideChar, "wchar_t", false);
4190
MAP(CChar8, "char8_t", false);
4291
MAP(CChar16, "char16_t", false);
4392
MAP(CChar32, "char32_t", false);
4493

94+
// Set after CChar32 to prefer char32_t for the shared underlying
95+
// Unicode.Scalar. char32_t is stable across platforms.
96+
MAP(CWideChar, "wchar_t", false);
97+
4598
MAP(CSignedChar, "signed char", false);
4699
MAP(CShort, "short", false);
47100
MAP(CInt, "int", false);
@@ -71,6 +124,8 @@ void PrimitiveTypeMapping::initialize(ASTContext &ctx) {
71124
MAP(Float32, "float", false);
72125
MAP(Float64, "double", false);
73126

127+
MAP(Float16, "_Float16", false);
128+
74129
MAP_CXX(Int, "NSInteger", "ptrdiff_t", "swift::Int", false);
75130
MAP_CXX(UInt, "NSUInteger", "size_t", "swift::UInt", false);
76131
MAP_C(Bool, "BOOL", "bool", false);
@@ -79,35 +134,40 @@ void PrimitiveTypeMapping::initialize(ASTContext &ctx) {
79134
MAP(UnsafeRawPointer, "void const *", true);
80135
MAP(UnsafeMutableRawPointer, "void *", true);
81136

82-
Identifier ID_ObjectiveC = ctx.Id_ObjectiveC;
83-
mappedTypeNames[{ID_ObjectiveC, ctx.getIdentifier("ObjCBool")}] = {
84-
"BOOL", std::nullopt, std::nullopt, false};
85-
mappedTypeNames[{ID_ObjectiveC, ctx.getIdentifier("Selector")}] = {
86-
"SEL", std::nullopt, std::nullopt, true};
87-
mappedTypeNames[{ID_ObjectiveC, ctx.getIdentifier(swift::getSwiftName(
88-
KnownFoundationEntity::NSZone))}] = {
89-
"struct _NSZone *", std::nullopt, std::nullopt, true};
137+
// Map other module types.
90138

91-
mappedTypeNames[{ctx.Id_Darwin, ctx.getIdentifier("DarwinBoolean")}] = {
92-
"Boolean", std::nullopt, std::nullopt, false};
139+
addMappedType(ctx.Id_ObjectiveC, ctx.getIdentifier("ObjCBool"),
140+
{"BOOL", std::nullopt, std::nullopt, false});
141+
addMappedType(ctx.Id_ObjectiveC, ctx.getIdentifier("Selector"),
142+
{"SEL", std::nullopt, std::nullopt, true});
143+
addMappedType(ctx.Id_ObjectiveC,
144+
ctx.getIdentifier(swift::getSwiftName(
145+
KnownFoundationEntity::NSZone)),
146+
{"struct _NSZone *", std::nullopt, std::nullopt, true});
93147

94-
mappedTypeNames[{ctx.Id_CoreGraphics, ctx.Id_CGFloat}] = {
95-
"CGFloat", std::nullopt, std::nullopt, false};
148+
addMappedType(ctx.Id_Darwin, ctx.getIdentifier("DarwinBoolean"),
149+
{"Boolean", std::nullopt, std::nullopt, false});
96150

97-
mappedTypeNames[{ctx.Id_CoreFoundation, ctx.Id_CGFloat}] = {
98-
"CGFloat", std::nullopt, std::nullopt, false};
151+
addMappedType(ctx.Id_CoreGraphics, ctx.Id_CGFloat,
152+
{"CGFloat", std::nullopt, std::nullopt, false});
153+
154+
addMappedType(ctx.Id_CoreFoundation, ctx.Id_CGFloat,
155+
{"CGFloat", std::nullopt, std::nullopt, false});
99156

100157
// Use typedefs we set up for SIMD vector types.
101158
#define MAP_SIMD_TYPE(BASENAME, _, __) \
102159
StringRef simd2##BASENAME = "swift_" #BASENAME "2"; \
103-
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "2")}] = { \
104-
simd2##BASENAME, simd2##BASENAME, simd2##BASENAME, false}; \
160+
addMappedType(ctx.Id_simd, ctx.getIdentifier(#BASENAME "2"), \
161+
{simd2##BASENAME, simd2##BASENAME, simd2##BASENAME, false}, \
162+
/*applyToUnderlying*/false); \
105163
StringRef simd3##BASENAME = "swift_" #BASENAME "3"; \
106-
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "3")}] = { \
107-
simd3##BASENAME, simd3##BASENAME, simd3##BASENAME, false}; \
164+
addMappedType(ctx.Id_simd, ctx.getIdentifier(#BASENAME "3"), \
165+
{simd3##BASENAME, simd3##BASENAME, simd3##BASENAME, false}, \
166+
/*applyToUnderlying*/false); \
108167
StringRef simd4##BASENAME = "swift_" #BASENAME "4"; \
109-
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "4")}] = { \
110-
simd4##BASENAME, simd4##BASENAME, simd4##BASENAME, false};
168+
addMappedType(ctx.Id_simd, ctx.getIdentifier(#BASENAME "4"), \
169+
{simd4##BASENAME, simd4##BASENAME, simd4##BASENAME, false}, \
170+
/*applyToUnderlying*/false);
111171
#include "swift/ClangImporter/SIMDMappedTypes.def"
112172
static_assert(SWIFT_MAX_IMPORTED_SIMD_ELEMENTS == 4,
113173
"must add or remove special name mappings if max number of "
@@ -119,9 +179,11 @@ PrimitiveTypeMapping::getMappedTypeInfoOrNull(const TypeDecl *typeDecl) {
119179
if (mappedTypeNames.empty())
120180
initialize(typeDecl->getASTContext());
121181

122-
Identifier moduleName = typeDecl->getModuleContext()->getName();
123-
Identifier name = typeDecl->getName();
124-
auto iter = mappedTypeNames.find({moduleName, name});
182+
auto nominal = dyn_cast<TypeDecl>(typeDecl);
183+
if (!nominal)
184+
return nullptr;
185+
186+
auto iter = mappedTypeNames.find(nominal);
125187
if (iter == mappedTypeNames.end())
126188
return nullptr;
127189
return &iter->second;

lib/PrintAsClang/PrimitiveTypeMapping.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#ifndef SWIFT_PRINTASCLANG_PRIMITIVETYPEMAPPING_H
1414
#define SWIFT_PRINTASCLANG_PRIMITIVETYPEMAPPING_H
1515

16-
#include "swift/AST/Identifier.h"
16+
#include "swift/AST/Decl.h"
1717
#include "swift/Basic/LLVM.h"
1818
#include "llvm/ADT/DenseMap.h"
1919

@@ -62,14 +62,14 @@ class PrimitiveTypeMapping {
6262

6363
FullClangTypeInfo *getMappedTypeInfoOrNull(const TypeDecl *typeDecl);
6464

65-
/// A map from {Module, TypeName} pairs to {C name, C nullability} pairs.
65+
/// Associate Swift types to their {name, nullability} in foreign languages.
6666
///
6767
/// This is populated on first use with a list of known Swift types that are
6868
/// translated directly by the ObjC printer instead of structurally, allowing
6969
/// it to do things like map 'Int' to 'NSInteger' and 'Float' to 'float'.
7070
/// In some sense it's the reverse of the ClangImporter's MappedTypes.def.
71-
llvm::DenseMap<std::pair<Identifier, Identifier>, FullClangTypeInfo>
72-
mappedTypeNames;
71+
/// Must be kept aligned with BuiltinMappedTypes.def.
72+
llvm::DenseMap<TypeDecl*, FullClangTypeInfo> mappedTypeNames;
7373
};
7474

7575
} // end namespace swift

test/PrintAsObjC/unicode-scalar-reference.swift

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,27 @@
55
// or actually be printed using a C / Objective-C compatible type.
66

77
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) \
8-
// RUN: %s -emit-module -verify -o %t \
8+
// RUN: %s -emit-module -verify -o %t -emit-module-doc \
99
// RUN: -emit-clang-header-path %t/compat.h
1010
// RUN: %FileCheck %s --input-file %t/compat.h
1111

1212
@_cdecl("referencesScalar")
1313
func referencesScalar() -> Unicode.Scalar { fatalError() }
14-
// CHECK: SWIFT_EXTERN Scalar referencesScalar(void)
14+
// CHECK: SWIFT_EXTERN char32_t referencesScalar(void)
15+
16+
@_cdecl("referencesRelated")
17+
func x_referencesRelated(a: CChar32, b: CWideChar) { }
18+
// CHECK: SWIFT_EXTERN void referencesRelated(char32_t a, wchar_t b)
19+
20+
#if !((os(macOS) || targetEnvironment(macCatalyst)) && arch(x86_64))
21+
// Actual test of Float16, on supported platforms.
22+
@_cdecl("referencesFloat16")
23+
func y_referencesFloat16(a: Float16, b: CFloat16) { }
24+
#else
25+
// Just print the expected string on macOS&x86_64 where there's no Float16.
26+
// This disables this one check on unsupported platforms.
27+
/// SWIFT_EXTERN void referencesFloat16(_Float16 a, _Float16 b)
28+
@_cdecl("printTheDoc")
29+
public func y_printTheDoc() { }
30+
#endif
31+
// CHECK: SWIFT_EXTERN void referencesFloat16(_Float16 a, _Float16 b)

0 commit comments

Comments
 (0)