Repository: swiftlang/swift
Pull request #80659: [cxx-interop] convert CXXForeignReferenceTypeInitializers into SuppressCXXForeignReferenceTypeInitializers to be an opt-out flag
Author: login: fahadnayyar
Labels: name: c++ interop
description: Feature: Interoperability with C++
Created: 2025-04-08T23:13:15Z | Merged: 2025-04-10T07:37:50Z

Turning the feature _"ctor of C++ foreign reference types is callable as Swift Initializers"_ on by default.

rdar://148285972



Diff:
diff --git a/include/swift/Basic/Features.def b/include/swift/Basic/Features.def
index 3cae686495893..47fc70414a90f 100644
--- a/include/swift/Basic/Features.def
+++ b/include/swift/Basic/Features.def
@@ -467,7 +467,7 @@ EXPERIMENTAL_FEATURE(ImportNonPublicCxxMembers, true)
 
 /// Synthesize static factory methods for C++ foreign reference types and import
 /// them as Swift initializers.
-EXPERIMENTAL_FEATURE(CXXForeignReferenceTypeInitializers, true)
+EXPERIMENTAL_FEATURE(SuppressCXXForeignReferenceTypeInitializers, true)
 
 // Isolated deinit
 SUPPRESSIBLE_LANGUAGE_FEATURE(IsolatedDeinit, 371, "isolated deinit")
diff --git a/lib/AST/FeatureSet.cpp b/lib/AST/FeatureSet.cpp
index d0e86f4df0360..a2bedb11dea61 100644
--- a/lib/AST/FeatureSet.cpp
+++ b/lib/AST/FeatureSet.cpp
@@ -425,7 +425,7 @@ UNINTERESTING_FEATURE(StrictMemorySafety)
 UNINTERESTING_FEATURE(SafeInteropWrappers)
 UNINTERESTING_FEATURE(AssumeResilientCxxTypes)
 UNINTERESTING_FEATURE(ImportNonPublicCxxMembers)
-UNINTERESTING_FEATURE(CXXForeignReferenceTypeInitializers)
+UNINTERESTING_FEATURE(SuppressCXXForeignReferenceTypeInitializers)
 UNINTERESTING_FEATURE(CoroutineAccessorsUnwindOnCallerError)
 UNINTERESTING_FEATURE(AllowRuntimeSymbolDeclarations)
 
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index dd95de89db4f2..6ec4f344f2d65 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -2539,8 +2539,8 @@ namespace {
           result->addMember(ctor);
         }
       } else {
-        if (Impl.SwiftContext.LangOpts.hasFeature(
-                Feature::CXXForeignReferenceTypeInitializers)) {
+        if (!Impl.SwiftContext.LangOpts.hasFeature(
+                Feature::SuppressCXXForeignReferenceTypeInitializers)) {
           assert(
               isa<ClassDecl>(result) &&
               "Expected result to be a ClassDecl as it cannot be a StructDecl");
@@ -3609,7 +3609,18 @@ namespace {
           isa<clang::FunctionDecl>(decl)
               ? cast<clang::FunctionDecl>(decl)->getReturnType()
               : cast<clang::ObjCMethodDecl>(decl)->getReturnType();
-      if (isForeignReferenceTypeWithoutImmortalAttrs(retType)) {
+      clang::QualType pointeeType = retType;
+      if (retType->isPointerType() || retType->isReferenceType()) {
+        pointeeType = retType->getPointeeType();
+      }
+
+      clang::RecordDecl *recordDecl = nullptr;
+      if (const auto *recordType = pointeeType->getAs<clang::RecordType>()) {
+        recordDecl = recordType->getDecl();
+      }
+
+      if (recordDecl && recordHasReferenceSemantics(recordDecl) &&
+          !hasImmortalAttrs(recordDecl)) {
         if (returnsRetainedAttrIsPresent && returnsUnretainedAttrIsPresent) {
           Impl.diagnose(loc, diag::both_returns_retained_returns_unretained,
                         decl);
diff --git a/lib/ClangImporter/SwiftDeclSynthesizer.cpp b/lib/ClangImporter/SwiftDeclSynthesizer.cpp
index 9c835ad038d80..9f6762e0107a0 100644
--- a/lib/ClangImporter/SwiftDeclSynthesizer.cpp
+++ b/lib/ClangImporter/SwiftDeclSynthesizer.cpp
@@ -2538,6 +2538,9 @@ llvm::SmallVector<clang::CXXMethodDecl *, 4>
 SwiftDeclSynthesizer::synthesizeStaticFactoryForCXXForeignRef(
     const clang::CXXRecordDecl *cxxRecordDecl) {
 
+  if (cxxRecordDecl->isAbstract())
+    return {};
+
   clang::ASTContext &clangCtx = cxxRecordDecl->getASTContext();
   clang::Sema &clangSema = ImporterImpl.getClangSema();
 
diff --git a/test/Interop/Cxx/class/constructors-diagnostics.swift b/test/Interop/Cxx/class/constructors-diagnostics.swift
index 7b61769752db6..aac0148066037 100644
--- a/test/Interop/Cxx/class/constructors-diagnostics.swift
+++ b/test/Interop/Cxx/class/constructors-diagnostics.swift
@@ -1,8 +1,7 @@
-// RUN: %target-swift-frontend -typecheck -verify -I %S/Inputs  %s -cxx-interoperability-mode=default -enable-experimental-feature CXXForeignReferenceTypeInitializers -disable-availability-checking -verify-additional-file %S/Inputs/constructors.h -Xcc -Wno-nullability-completeness
+// RUN: %target-swift-frontend -typecheck -verify -I %S/Inputs  %s -cxx-interoperability-mode=default -disable-availability-checking -verify-additional-file %S/Inputs/constructors.h -Xcc -Wno-nullability-completeness
 
-// This test uses -verify-additional-file, which do not work well on Windows:
+// This test uses -verify-additional-file, which do not work well on Windows.
 // UNSUPPORTED: OS=windows-msvc
-// REQUIRES: swift_feature_CXXForeignReferenceTypeInitializers
 
 import Constructors
 
diff --git a/test/Interop/Cxx/class/constructors-executable.swift b/test/Interop/Cxx/class/constructors-executable.swift
index fc0142d4ce19a..d28898159cb9b 100644
--- a/test/Interop/Cxx/class/constructors-executable.swift
+++ b/test/Interop/Cxx/class/constructors-executable.swift
@@ -1,7 +1,6 @@
-// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -cxx-interoperability-mode=default -enable-experimental-feature CXXForeignReferenceTypeInitializers -Xfrontend -disable-availability-checking)
+// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -cxx-interoperability-mode=default -Xfrontend -disable-availability-checking)
 //
 // REQUIRES: executable_test
-// REQUIRES: swift_feature_CXXForeignReferenceTypeInitializers
 
 import Constructors
 import CxxStdlib
diff --git a/test/Interop/Cxx/foreign-reference/Inputs/inheritance.h b/test/Interop/Cxx/foreign-reference/Inputs/inheritance.h
index bbe1d12ba2ce9..91db728a6e498 100644
--- a/test/Interop/Cxx/foreign-reference/Inputs/inheritance.h
+++ b/test/Interop/Cxx/foreign-reference/Inputs/inheritance.h
@@ -109,7 +109,7 @@ __attribute__((swift_attr("release:immortal"))) ImmortalRefType {};
 ImmortalRefType *returnImmortalRefType() { return new ImmortalRefType(); };
 
 struct DerivedFromImmortalRefType : ImmortalRefType {};
-DerivedFromImmortalRefType *returnDerivedFromImmortalRefType() {
+DerivedFromImmortalRefType *returnDerivedFromImmortalRefType() { // expected-warning {{'returnDerivedFromImmortalRefType' should be annotated with either SWIFT_RETURNS_RETAINED or SWIFT_RETURNS_UNRETAINED as it is returning a SWIFT_SHARED_REFERENCE}}
     return new DerivedFromImmortalRefType();
 };
 
@@ -138,7 +138,7 @@ DerivedFromValueTypeAndAnnotated *returnDerivedFromValueTypeAndAnnotated() { //
 }
 
 struct DerivedFromRefType final : RefType {};
-DerivedFromRefType *returnDerivedFromRefType() {
+DerivedFromRefType *returnDerivedFromRefType() { // expected-warning {{'returnDerivedFromRefType' should be annotated with either SWIFT_RETURNS_RETAINED or SWIFT_RETURNS_UNRETAINED as it is returning a SWIFT_SHARED_REFERENCE}}
     return new DerivedFromRefType();
 }
 
@@ -209,7 +209,7 @@ __attribute__((swift_attr("release:RCRelease"))) RefType {};
 RefType *returnRefType() { return new RefType(); }; // expected-warning {{'returnRefType' should be annotated with either SWIFT_RETURNS_RETAINED or SWIFT_RETURNS_UNRETAINED as it is returning a SWIFT_SHARED_REFERENC}}
 
 struct DerivedFromRefType final : RefType {};
-DerivedFromRefType *returnDerivedFromRefType() { // TODO: rdar://145098078 Missing SWIFT_RETURNS_(UN)RETAINED annotation warning should trigger for inferred foreeign reference types as well
+DerivedFromRefType *returnDerivedFromRefType() { // expected-warning {{'returnDerivedFromRefType' should be annotated with either SWIFT_RETURNS_RETAINED or SWIFT_RETURNS_UNRETAINED as it is returning a SWIFT_SHARED_REFERENCE}}
   return new DerivedFromRefType();
 };
 } // namespace BasicInheritanceExample
@@ -236,7 +236,7 @@ DerivedFromBaseRef1AndBaseRef2 *returnDerivedFromBaseRef1AndBaseRef2() {
 };
 
 struct DerivedFromBaseRef3 : BaseRef3 {};
-DerivedFromBaseRef3 *returnDerivedFromBaseRef3() {
+DerivedFromBaseRef3 *returnDerivedFromBaseRef3() { // expected-warning {{'returnDerivedFromBaseRef3' should be annotated with either SWIFT_RETURNS_RETAINED or SWIFT_RETURNS_UNRETAINED as it is returning a SWIFT_SHARED_REFERENCE}}
   return new DerivedFromBaseRef3();
 };
 } // namespace MultipleInheritanceExample1
@@ -312,7 +312,7 @@ __attribute__((swift_attr("release:samerelease"))) B2 {};  // expected-error {{m
 
 struct D : B1, B2 {}; // expected-error {{multiple functions 'sameretain' found; there must be exactly one retain function for reference type 'D'}}
                       // expected-error@-1 {{multiple functions 'samerelease' found; there must be exactly one release function for reference type 'D'}}
-D *returnD() { return new D(); };
+D *returnD() { return new D(); }; // expected-warning {{'returnD' should be annotated with either SWIFT_RETURNS_RETAINED or SWIFT_RETURNS_UNRETAINED as it is returning a SWIFT_SHARED_REFERENCE}}
 } // namespace OverloadedRetainRelease
 
 void sameretain(OverloadedRetainRelease::B1 *v) {}
@@ -339,7 +339,7 @@ struct BVirtual : virtual A {};
 struct CVirtual : virtual A {};
 
 struct VirtualDiamond : BVirtual, CVirtual {};
-VirtualDiamond *returnVirtualDiamond() { return new VirtualDiamond(); };
+VirtualDiamond *returnVirtualDiamond() { return new VirtualDiamond(); }; // expected-warning {{'returnVirtualDiamond' should be annotated with either SWIFT_RETURNS_RETAINED or SWIFT_RETURNS_UNRETAINED as it is returning a SWIFT_SHARED_REFERENCE}}
 } // namespace RefTypeDiamondInheritance
 
 void retainA(RefTypeDiamondInheritance::A *a) {};
@@ -355,7 +355,7 @@ __attribute__((swift_attr("release:releaseB"))) B : A {};
 struct C : A {};
 
 struct Diamond : B, C {};
-Diamond *returnDiamond() { return new Diamond(); };
+Diamond *returnDiamond() { return new Diamond(); }; // expected-warning {{'returnDiamond' should be annotated with either SWIFT_RETURNS_RETAINED or SWIFT_RETURNS_UNRETAINED as it is returning a SWIFT_SHARED_REFERENCE}}
 
 } // namespace NonRefTypeDiamondInheritance
 
@@ -384,7 +384,7 @@ __attribute__((swift_attr("retain:forestRetain"))) __attribute__((
 };
 
 class Forest : public IntrusiveRefCountedTemplate<Forest> {};
-Forest *returnForest() { return new Forest(); };
+Forest *returnForest() { return new Forest(); }; // expected-warning {{'returnForest' should be annotated with either SWIFT_RETURNS_RETAINED or SWIFT_RETURNS_UNRETAINED as it is returning a SWIFT_SHARED_REFERENCE}}
 } // namespace InheritingTemplatedRefType
 
 void forestRetain(InheritingTemplatedRefType::IntrusiveRefCountedTemplate<
diff --git a/test/Interop/Cxx/foreign-reference/no-ctor-errors.swift b/test/Interop/Cxx/foreign-reference/cxx-frt-ctor-callable.swift
similarity index 61%
rename from test/Interop/Cxx/foreign-reference/no-ctor-errors.swift
rename to test/Interop/Cxx/foreign-reference/cxx-frt-ctor-callable.swift
index b8155509e8f9a..a90f4f28f3618 100644
--- a/test/Interop/Cxx/foreign-reference/no-ctor-errors.swift
+++ b/test/Interop/Cxx/foreign-reference/cxx-frt-ctor-callable.swift
@@ -1,6 +1,6 @@
 // RUN: rm -rf %t
 // RUN: split-file %s %t
-// RUN: not %target-swift-frontend -typecheck -I %t/Inputs  %t/test.swift  -enable-experimental-cxx-interop 2>&1 | %FileCheck %s
+// RUN: %target-swift-frontend -typecheck -verify -I %t/Inputs  %t/test.swift  -enable-experimental-cxx-interop -disable-availability-checking
 
 //--- Inputs/module.modulemap
 module Test {
@@ -21,5 +21,4 @@ HasCtor {
 
 import Test
 
-// CHECK: error: 'HasCtor' cannot be constructed because it has no accessible initializers
-let x = HasCtor(42)
\ No newline at end of file
+let x = HasCtor(42)
diff --git a/test/Interop/Cxx/foreign-reference/move-only-module-interface.swift b/test/Interop/Cxx/foreign-reference/move-only-module-interface.swift
index 82389914336ba..f20f81ac32e84 100644
--- a/test/Interop/Cxx/foreign-reference/move-only-module-interface.swift
+++ b/test/Interop/Cxx/foreign-reference/move-only-module-interface.swift
@@ -1,7 +1,7 @@
 // RUN: %target-swift-ide-test -print-module -module-to-print=MoveOnly -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s
 
 // CHECK: class MoveOnly {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> MoveOnly
@@ -9,14 +9,14 @@
 // CHECK-NOT: func moveIntoResult(_ x: MoveOnly) -> MoveOnly
 
 // CHECK: class HasMoveOnlyChild {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK-NOT: var child: MoveOnly
 // CHECK:   class func create() -> HasMoveOnlyChild
 // CHECK: }
 // CHECK-NOT: func moveIntoResult(_ x: HasMoveOnlyChild) -> HasMoveOnlyChild
 
 // CHECK: class PrivateCopyCtor {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> PrivateCopyCtor
@@ -24,7 +24,7 @@
 // CHECK-NOT: func moveIntoResult(_ x: PrivateCopyCtor) -> PrivateCopyCtor
 
 // CHECK: class BadCopyCtor {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> BadCopyCtor
diff --git a/test/Interop/Cxx/foreign-reference/pod-module-interface.swift b/test/Interop/Cxx/foreign-reference/pod-module-interface.swift
index 5e3f950aaff43..984ac99257cf6 100644
--- a/test/Interop/Cxx/foreign-reference/pod-module-interface.swift
+++ b/test/Interop/Cxx/foreign-reference/pod-module-interface.swift
@@ -1,7 +1,7 @@
 // RUN: %target-swift-ide-test -print-module -module-to-print=POD -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s
 
 // CHECK: class Empty {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> Empty
@@ -12,14 +12,14 @@
 // CHECK-NOT: func passThroughByValue(_ x: Empty) -> Empty
 
 // CHECK: class MultipleAttrs {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> MultipleAttrs
 // CHECK: }
 
 // CHECK: class IntPair {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   func instancePassThroughByRef(_ ref: IntPair) -> IntPair
@@ -33,7 +33,7 @@
 // CHECK: func passThroughByRef(_ x: IntPair) -> IntPair
 
 // CHECK: class RefHoldingPair {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK-NOT: pair
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
@@ -42,7 +42,7 @@
 // CHECK: }
 
 // CHECK: class RefHoldingPairRef {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> RefHoldingPairRef
@@ -51,7 +51,7 @@
 // CHECK: }
 
 // CHECK: class RefHoldingPairPtr {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> RefHoldingPairPtr
@@ -60,7 +60,6 @@
 // CHECK: }
 
 // CHECK: struct ValueHoldingPair {
-// CHECK-NOT: init
 // CHECK-NOT: pair
 // CHECK:   init()
 // CHECK:   func test() -> Int32
@@ -77,7 +76,7 @@
 // CHECK: }
 
 // CHECK: class BigType {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> BigType
diff --git a/test/Interop/Cxx/foreign-reference/singleton-module-interface.swift b/test/Interop/Cxx/foreign-reference/singleton-module-interface.swift
index 83a1e95d763e7..bca9a093f2d06 100644
--- a/test/Interop/Cxx/foreign-reference/singleton-module-interface.swift
+++ b/test/Interop/Cxx/foreign-reference/singleton-module-interface.swift
@@ -1,7 +1,7 @@
 // RUN: %target-swift-ide-test -print-module -module-to-print=Singleton -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s
 
 // CHECK: class DeletedDtor {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> DeletedDtor
@@ -10,7 +10,7 @@
 // CHECK: func mutateIt(_ x: DeletedDtor)
 
 // CHECK: class PrivateDtor {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> PrivateDtor
@@ -19,7 +19,7 @@
 // CHECK: func mutateIt(_ x: PrivateDtor)
 
 // CHECK: class DeletedSpecialMembers {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> DeletedSpecialMembers
@@ -28,7 +28,7 @@
 // CHECK: func mutateIt(_ x: DeletedSpecialMembers)
 
 // CHECK: class PrivateSpecialMembers {
-// CHECK-NOT: init
+// CHECK: init
 // CHECK:   func test() -> Int32
 // CHECK:   func testMutable() -> Int32
 // CHECK:   class func create() -> PrivateSpecialMembers
diff --git a/test/Interop/Cxx/symbolic-imports/print-symbolic-module-interface.swift b/test/Interop/Cxx/symbolic-imports/print-symbolic-module-interface.swift
index 21fdcbefd8cac..a52236c518253 100644
--- a/test/Interop/Cxx/symbolic-imports/print-symbolic-module-interface.swift
+++ b/test/Interop/Cxx/symbolic-imports/print-symbolic-module-interface.swift
@@ -119,6 +119,7 @@ struct NonCopyable {
 // CHECK-NEXT:   }
 // CHECK-NEXT: }
 // CHECK: class MyImmortal {
+// CHECK-NEXT:     init
 // CHECK-NEXT:   func foo()
 // CHECK-NEXT: }
 // CHECK-NEXT: struct NonCopyable {


Reviews:
user: login: Xazax-hun
body: I see that this is already merged. Could you address the reviews in a follow-up?

Also, I strongly discourage PRs that are changing two unrelated features at the same time. The changes to importing the FRT ctors and the changes to the diagnostics could have been two independent PRs, I don't see any dependencies between them. 

Edit: my concerns are now resolved.

state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T10:42:51Z
user: login: Xazax-hun
body: We talked offline. The seemingly unrelated and untested changes were all responses to existing tests failing so everything should have at least indirect test coverage. Moreover, every change in this PR is actually motivated. The UI does not let me approve the PR, but I consider this approved on my end. The nits can be fixed in a follow-up. 
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T18:41:03Z

Review comments:
diff_hunk: @@ -2538,6 +2538,9 @@ llvm::SmallVector<clang::CXXMethodDecl *, 4>
 SwiftDeclSynthesizer::synthesizeStaticFactoryForCXXForeignRef(
     const clang::CXXRecordDecl *cxxRecordDecl) {
 
+  if (cxxRecordDecl->isAbstract())
path: lib/ClangImporter/SwiftDeclSynthesizer.cpp
user: login: Xazax-hun
body: Do we have a test covering this branch? I am ok with the change but would be nice to have it actually tested. 
created_at: 2025-04-10T10:39:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,7 +1,7 @@
 // RUN: %target-swift-ide-test -print-module -module-to-print=POD -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s
 
 // CHECK: class Empty {
-// CHECK-NOT: init
+// CHECK: init
path: test/Interop/Cxx/foreign-reference/pod-module-interface.swift
user: login: Xazax-hun
body: Nit: I think it is not the right indentation.
created_at: 2025-04-10T10:40:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -119,6 +119,7 @@ struct NonCopyable {
 // CHECK-NEXT:   }
 // CHECK-NEXT: }
 // CHECK: class MyImmortal {
+// CHECK-NEXT:     init
path: test/Interop/Cxx/symbolic-imports/print-symbolic-module-interface.swift
user: login: Xazax-hun
body: Nit: indent  the same as the function below. 
created_at: 2025-04-10T10:40:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3609,7 +3609,18 @@ namespace {
           isa<clang::FunctionDecl>(decl)
               ? cast<clang::FunctionDecl>(decl)->getReturnType()
               : cast<clang::ObjCMethodDecl>(decl)->getReturnType();
-      if (isForeignReferenceTypeWithoutImmortalAttrs(retType)) {
+      clang::QualType pointeeType = retType;
path: lib/ClangImporter/ImportDecl.cpp
user: login: Xazax-hun
body: This was the only use of `isForeignReferenceTypeWithoutImmortalAttrs`. I think we could have fixed that function. Now I think it is unused so let's remove it. 
created_at: 2025-04-10T10:41:41Z
author_association: CONTRIBUTOR

PR comments:
user: login: fahadnayyar
created_at: 2025-04-10T02:54:02Z
body: @swift-ci please smoke test
author_association: CONTRIBUTOR
user: login: fahadnayyar
created_at: 2025-04-10T04:54:04Z
body: NOTE: I am addressing rdar://145098078 as well in this patch. 
`SWIFT_RETURNS_(UN)RETAINED` related diagnostics (specially the warning in case of  unannotated C++ APIs returning `SWIFT_SHARED_REFERENCE` types) were not triggering for cases where the return type in the C++ API is not annotated with `SWIFT_SHARED_REFERENCE` directly but it derives the reference semantics from one of its parent type via C++ inheritance. 

We still need to address rdar://148952864 which is a minor bug. Now we also see diagnostics for C++ APIs returning a type which was derived from a `SWIFT_IMMORTAL_REFERNECE`. The diagnostic does not trigger when return type is `SWIFT_IMMORTAL_REFERNECE` but only when `IMMORTAL_REFERNECE` behaviour is inferred from a base type via C++ inheritance. 
author_association: CONTRIBUTOR