@@ -201,6 +201,13 @@ namespace {
201201 : ImportHint::OtherPointer};
202202 }
203203
204+ static bool
205+ isDirectUseOfForeignReferenceType (clang::QualType clangPointeeType,
206+ Type swiftPointeeType) {
207+ return swiftPointeeType && swiftPointeeType->isForeignReferenceType () &&
208+ !clangPointeeType->isPointerType ();
209+ }
210+
204211 class SwiftTypeConverter :
205212 public clang::TypeVisitor<SwiftTypeConverter, ImportResult>
206213 {
@@ -494,9 +501,10 @@ namespace {
494501 pointeeQualType, ImportTypeKind::Value, addImportDiagnostic,
495502 AllowNSUIntegerAsInt, Bridgeability::None, ImportTypeAttrs ());
496503
497- // If this is imported as a reference type, ignore the pointer.
498- if (pointeeType && pointeeType->isForeignReferenceType ())
499- return {pointeeType, ImportHint::OtherPointer};
504+ // If this is imported as a reference type, ignore the innermost pointer.
505+ // (`T *` becomes `T`, but `T **` becomes `UnsafeMutablePointer<T>`.)
506+ if (isDirectUseOfForeignReferenceType (pointeeQualType, pointeeType))
507+ return {pointeeType, ImportHint::OtherPointer};
500508
501509 // If the pointed-to type is unrepresentable in Swift, or its C
502510 // alignment is greater than the maximum Swift alignment, import as
@@ -585,7 +593,7 @@ namespace {
585593 if (!pointeeType)
586594 return Type ();
587595
588- if (pointeeType-> isForeignReferenceType ( ))
596+ if (isDirectUseOfForeignReferenceType (pointeeQualType, pointeeType ))
589597 return {pointeeType, ImportHint::None};
590598
591599 if (pointeeQualType->isFunctionType ()) {
@@ -2524,6 +2532,15 @@ ClangImporter::Implementation::importParameterType(
25242532 swiftParamTy = importedType.getType ();
25252533 }
25262534
2535+ // `isInOut` is set above if we stripped off a mutable `&` before importing
2536+ // the type. Normally, we want to use an `inout` parameter in this situation.
2537+ // However, if the parameter belongs to a foreign reference type *and* the
2538+ // reference we stripped out was directly to that type (rather than to a
2539+ // pointer to that type), the foreign reference type should "eat" the
2540+ // indirection of the `&`, so we *don't* want to use an `inout` parameter.
2541+ if (isInOut && isDirectUseOfForeignReferenceType (paramTy, swiftParamTy))
2542+ isInOut = false ;
2543+
25272544 return ImportParameterTypeResult{swiftParamTy, isInOut,
25282545 isParamTypeImplicitlyUnwrapped};
25292546}
@@ -2615,9 +2632,8 @@ static ParamDecl *getParameterInfo(ClangImporter::Implementation *impl,
26152632
26162633 // Foreign references are already references so they don't need to be passed
26172634 // as inout.
2618- paramInfo->setSpecifier (isInOut && !swiftParamTy->isForeignReferenceType ()
2619- ? ParamSpecifier::InOut
2620- : ParamSpecifier::Default);
2635+ paramInfo->setSpecifier (isInOut ? ParamSpecifier::InOut
2636+ : ParamSpecifier::Default);
26212637 paramInfo->setInterfaceType (swiftParamTy);
26222638 impl->recordImplicitUnwrapForDecl (paramInfo, isParamTypeImplicitlyUnwrapped);
26232639
0 commit comments