@@ -201,6 +201,13 @@ namespace {
201
201
: ImportHint::OtherPointer};
202
202
}
203
203
204
+ static bool
205
+ isDirectUseOfForeignReferenceType (clang::QualType clangPointeeType,
206
+ Type swiftPointeeType) {
207
+ return swiftPointeeType && swiftPointeeType->isForeignReferenceType () &&
208
+ !clangPointeeType->isPointerType ();
209
+ }
210
+
204
211
class SwiftTypeConverter :
205
212
public clang::TypeVisitor<SwiftTypeConverter, ImportResult>
206
213
{
@@ -494,9 +501,10 @@ namespace {
494
501
pointeeQualType, ImportTypeKind::Value, addImportDiagnostic,
495
502
AllowNSUIntegerAsInt, Bridgeability::None, ImportTypeAttrs ());
496
503
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};
500
508
501
509
// If the pointed-to type is unrepresentable in Swift, or its C
502
510
// alignment is greater than the maximum Swift alignment, import as
@@ -585,7 +593,7 @@ namespace {
585
593
if (!pointeeType)
586
594
return Type ();
587
595
588
- if (pointeeType-> isForeignReferenceType ( ))
596
+ if (isDirectUseOfForeignReferenceType (pointeeQualType, pointeeType ))
589
597
return {pointeeType, ImportHint::None};
590
598
591
599
if (pointeeQualType->isFunctionType ()) {
@@ -2524,6 +2532,15 @@ ClangImporter::Implementation::importParameterType(
2524
2532
swiftParamTy = importedType.getType ();
2525
2533
}
2526
2534
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
+
2527
2544
return ImportParameterTypeResult{swiftParamTy, isInOut,
2528
2545
isParamTypeImplicitlyUnwrapped};
2529
2546
}
@@ -2615,9 +2632,8 @@ static ParamDecl *getParameterInfo(ClangImporter::Implementation *impl,
2615
2632
2616
2633
// Foreign references are already references so they don't need to be passed
2617
2634
// as inout.
2618
- paramInfo->setSpecifier (isInOut && !swiftParamTy->isForeignReferenceType ()
2619
- ? ParamSpecifier::InOut
2620
- : ParamSpecifier::Default);
2635
+ paramInfo->setSpecifier (isInOut ? ParamSpecifier::InOut
2636
+ : ParamSpecifier::Default);
2621
2637
paramInfo->setInterfaceType (swiftParamTy);
2622
2638
impl->recordImplicitUnwrapForDecl (paramInfo, isParamTypeImplicitlyUnwrapped);
2623
2639
0 commit comments