@@ -133,18 +133,30 @@ class CFunctionSignatureTypePrinter
133133 visitPart (aliasTy->getSinglyDesugaredType (), optionalKind, isInOutParam);
134134 }
135135
136+ void visitEnumType (EnumType *ET, Optional<OptionalTypeKind> optionalKind,
137+ bool isInOutParam) {
138+ visitValueType (ET, optionalKind, isInOutParam);
139+ }
140+
136141 void visitStructType (StructType *ST, Optional<OptionalTypeKind> optionalKind,
137142 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));
139151
140152 // Handle known type names.
141- if (printIfKnownSimpleType (SD , optionalKind, isInOutParam))
153+ if (printIfKnownSimpleType (decl , optionalKind, isInOutParam))
142154 return ;
143155 // FIXME: Handle optional structures.
144156 if (typeUseKind == FunctionSignatureTypeUse::ParamType) {
145157 if (languageMode != OutputLanguageMode::Cxx &&
146- (SD ->isResilient () ||
147- interopContext.getIrABIDetails ().shouldPassIndirectly (ST ))) {
158+ (decl ->isResilient () ||
159+ interopContext.getIrABIDetails ().shouldPassIndirectly (NT ))) {
148160 if (modifiersDelegate.prefixIndirectParamValueTypeInC )
149161 (*modifiersDelegate.prefixIndirectParamValueTypeInC )(os);
150162 // FIXME: it would be nice to print out the C struct type here.
@@ -156,11 +168,11 @@ class CFunctionSignatureTypePrinter
156168
157169 } else {
158170 ClangValueTypePrinter (os, cPrologueOS, typeMapping, interopContext)
159- .printValueTypeParameterType (SD , languageMode, isInOutParam);
171+ .printValueTypeParameterType (decl , languageMode, isInOutParam);
160172 }
161173 } else
162174 ClangValueTypePrinter (os, cPrologueOS, typeMapping, interopContext)
163- .printValueTypeReturnType (SD , languageMode);
175+ .printValueTypeReturnType (decl , languageMode);
164176 }
165177
166178 void visitPart (Type Ty, Optional<OptionalTypeKind> optionalKind,
@@ -297,16 +309,19 @@ void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
297309 Type type, StringRef name, bool isInOut, bool isIndirect,
298310 llvm::Optional<AdditionalParam::Role> paramRole) {
299311 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+ }
310325 }
311326 }
312327 // Primitive types are passed directly without any conversions.
@@ -368,23 +383,26 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
368383
369384 // Values types are returned either direcly in their C representation, or
370385 // 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 ;
386405 }
387- return ;
388406 }
389407 }
390408
@@ -476,3 +494,14 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
476494 /* isIndirect=*/ false }});
477495 os << " }\n " ;
478496}
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