@@ -133,18 +133,30 @@ class CFunctionSignatureTypePrinter
133
133
visitPart (aliasTy->getSinglyDesugaredType (), optionalKind, isInOutParam);
134
134
}
135
135
136
+ void visitEnumType (EnumType *ET, Optional<OptionalTypeKind> optionalKind,
137
+ bool isInOutParam) {
138
+ visitValueType (ET, optionalKind, isInOutParam);
139
+ }
140
+
136
141
void visitStructType (StructType *ST, Optional<OptionalTypeKind> optionalKind,
137
142
bool isInOutParam) {
138
- const StructDecl *SD = ST->getStructOrBoundGenericStruct ();
143
+ visitValueType (ST, optionalKind, isInOutParam);
144
+ }
145
+
146
+ void visitValueType (NominalType *NT, Optional<OptionalTypeKind> optionalKind,
147
+ bool isInOutParam) {
148
+ assert (isa<StructType>(NT) || isa<EnumType>(NT));
149
+ const auto *decl = NT->getNominalOrBoundGenericNominal ();
150
+ assert (isa<StructDecl>(decl) || isa<EnumDecl>(decl));
139
151
140
152
// Handle known type names.
141
- if (printIfKnownSimpleType (SD , optionalKind, isInOutParam))
153
+ if (printIfKnownSimpleType (decl , optionalKind, isInOutParam))
142
154
return ;
143
155
// FIXME: Handle optional structures.
144
156
if (typeUseKind == FunctionSignatureTypeUse::ParamType) {
145
157
if (languageMode != OutputLanguageMode::Cxx &&
146
- (SD ->isResilient () ||
147
- interopContext.getIrABIDetails ().shouldPassIndirectly (ST ))) {
158
+ (decl ->isResilient () ||
159
+ interopContext.getIrABIDetails ().shouldPassIndirectly (NT ))) {
148
160
if (modifiersDelegate.prefixIndirectParamValueTypeInC )
149
161
(*modifiersDelegate.prefixIndirectParamValueTypeInC )(os);
150
162
// FIXME: it would be nice to print out the C struct type here.
@@ -156,11 +168,11 @@ class CFunctionSignatureTypePrinter
156
168
157
169
} else {
158
170
ClangValueTypePrinter (os, cPrologueOS, typeMapping, interopContext)
159
- .printValueTypeParameterType (SD , languageMode, isInOutParam);
171
+ .printValueTypeParameterType (decl , languageMode, isInOutParam);
160
172
}
161
173
} else
162
174
ClangValueTypePrinter (os, cPrologueOS, typeMapping, interopContext)
163
- .printValueTypeReturnType (SD , languageMode);
175
+ .printValueTypeReturnType (decl , languageMode);
164
176
}
165
177
166
178
void visitPart (Type Ty, Optional<OptionalTypeKind> optionalKind,
@@ -297,16 +309,19 @@ void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
297
309
Type type, StringRef name, bool isInOut, bool isIndirect,
298
310
llvm::Optional<AdditionalParam::Role> paramRole) {
299
311
auto namePrinter = [&]() { ClangSyntaxPrinter (os).printIdentifier (name); };
300
- if (!isKnownCxxType (type, typeMapping)) {
301
- if (auto *structDecl = type->getStructOrBoundGenericStruct ()) {
302
- ClangValueTypePrinter (os, cPrologueOS, typeMapping, interopContext)
303
- .printParameterCxxToCUseScaffold (
304
- isIndirect || structDecl->isResilient () ||
305
- interopContext.getIrABIDetails ().shouldPassIndirectly (type),
306
- structDecl, namePrinter, isInOut,
307
- /* isSelf=*/ paramRole &&
308
- *paramRole == AdditionalParam::Role::Self);
309
- return ;
312
+ if (!isKnownCxxType (type, typeMapping) &&
313
+ !hasKnownOptionalNullableCxxMapping (type)) {
314
+ if (auto *decl = type->getNominalOrBoundGenericNominal ()) {
315
+ if ((isa<StructDecl>(decl) || isa<EnumDecl>(decl))) {
316
+ ClangValueTypePrinter (os, cPrologueOS, typeMapping, interopContext)
317
+ .printParameterCxxToCUseScaffold (
318
+ isIndirect || decl->isResilient () ||
319
+ interopContext.getIrABIDetails ().shouldPassIndirectly (type),
320
+ decl, namePrinter, isInOut,
321
+ /* isSelf=*/ paramRole &&
322
+ *paramRole == AdditionalParam::Role::Self);
323
+ return ;
324
+ }
310
325
}
311
326
}
312
327
// Primitive types are passed directly without any conversions.
@@ -368,23 +383,26 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
368
383
369
384
// Values types are returned either direcly in their C representation, or
370
385
// indirectly by a pointer.
371
- if (!isKnownCxxType (resultTy, typeMapping)) {
372
- if (auto *structDecl = resultTy->getStructOrBoundGenericStruct ()) {
373
- bool isIndirect =
374
- structDecl->isResilient () ||
375
- interopContext.getIrABIDetails ().shouldReturnIndirectly (resultTy);
376
- ClangValueTypePrinter valueTypePrinter (os, cPrologueOS, typeMapping,
377
- interopContext);
378
- if (isIndirect) {
379
- valueTypePrinter.printValueTypeIndirectReturnScaffold (
380
- structDecl, [&](StringRef returnParam) {
381
- printCallToCFunc (/* additionalParam=*/ returnParam);
382
- });
383
- } else {
384
- valueTypePrinter.printValueTypeDirectReturnScaffold (
385
- structDecl, [&]() { printCallToCFunc (/* additionalParam=*/ None); });
386
+ if (!isKnownCxxType (resultTy, typeMapping) &&
387
+ !hasKnownOptionalNullableCxxMapping (resultTy)) {
388
+ if (auto *decl = resultTy->getNominalOrBoundGenericNominal ()) {
389
+ if ((isa<StructDecl>(decl) || isa<EnumDecl>(decl))) {
390
+ bool isIndirect =
391
+ decl->isResilient () ||
392
+ interopContext.getIrABIDetails ().shouldReturnIndirectly (resultTy);
393
+ ClangValueTypePrinter valueTypePrinter (os, cPrologueOS, typeMapping,
394
+ interopContext);
395
+ if (isIndirect) {
396
+ valueTypePrinter.printValueTypeIndirectReturnScaffold (
397
+ decl, [&](StringRef returnParam) {
398
+ printCallToCFunc (/* additionalParam=*/ returnParam);
399
+ });
400
+ } else {
401
+ valueTypePrinter.printValueTypeDirectReturnScaffold (
402
+ decl, [&]() { printCallToCFunc (/* additionalParam=*/ None); });
403
+ }
404
+ return ;
386
405
}
387
- return ;
388
406
}
389
407
}
390
408
@@ -476,3 +494,14 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
476
494
/* isIndirect=*/ false }});
477
495
os << " }\n " ;
478
496
}
497
+
498
+ bool DeclAndTypeClangFunctionPrinter::hasKnownOptionalNullableCxxMapping (
499
+ Type type) {
500
+ if (auto optionalObjectType = type->getOptionalObjectType ()) {
501
+ if (auto typeInfo = typeMapping.getKnownCxxTypeInfo (
502
+ optionalObjectType->getNominalOrBoundGenericNominal ())) {
503
+ return typeInfo->canBeNullable ;
504
+ }
505
+ }
506
+ return false ;
507
+ }
0 commit comments