diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt index 90f44249dc1..b635aa807d5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportMapper.kt @@ -118,15 +118,26 @@ internal fun ObjCExportMapper.getDeprecation(descriptor: DeclarationDescriptor): return null } -private tailrec fun ObjCExportMapper.isHiddenByDeprecation(descriptor: ClassDescriptor): Boolean { +private fun ObjCExportMapper.isHiddenByDeprecation(descriptor: ClassDescriptor): Boolean { if (deprecationResolver == null) return false if (deprecationResolver.isDeprecatedHidden(descriptor)) return true - val superClass = descriptor.getSuperClassNotAny() ?: return false - // Note: ObjCExport requires super class of exposed class to be exposed. // So hide a class if its super class is hidden: - return isHiddenByDeprecation(superClass) + val superClass = descriptor.getSuperClassNotAny() + if (superClass != null && isHiddenByDeprecation(superClass)) { + return true + } + + // Note: ObjCExport requires enclosing class of exposed class to be exposed. + // Also in Kotlin hidden class members (including other classes) aren't directly accessible. + // So hide a class if its enclosing class is hidden: + val containingDeclaration = descriptor.containingDeclaration + if (containingDeclaration is ClassDescriptor && isHiddenByDeprecation(containingDeclaration)) { + return true + } + + return false } // Note: the logic is partially duplicated in ObjCExportLazyImpl.translateClasses. diff --git a/backend.native/tests/framework/values/expectedLazy.h b/backend.native/tests/framework/values/expectedLazy.h index bf0e630d586..f1dd07724bd 100644 --- a/backend.native/tests/framework/values/expectedLazy.h +++ b/backend.native/tests/framework/values/expectedLazy.h @@ -658,6 +658,19 @@ __attribute__((swift_name("TestDeprecation"))) - (void)openWarning __attribute__((swift_name("openWarning()"))) __attribute__((deprecated("warning"))); - (void)normal __attribute__((swift_name("normal()"))); - (int32_t)openNormal __attribute__((swift_name("openNormal()"))); +- (void)testHiddenNested:(id)hiddenNested __attribute__((swift_name("test(hiddenNested:)"))); +- (void)testHiddenNestedNested:(id)hiddenNestedNested __attribute__((swift_name("test(hiddenNestedNested:)"))); +- (void)testHiddenNestedInner:(id)hiddenNestedInner __attribute__((swift_name("test(hiddenNestedInner:)"))); +- (void)testHiddenInner:(id)hiddenInner __attribute__((swift_name("test(hiddenInner:)"))); +- (void)testHiddenInnerInner:(id)hiddenInnerInner __attribute__((swift_name("test(hiddenInnerInner:)"))); +- (void)testTopLevelHidden:(id)topLevelHidden __attribute__((swift_name("test(topLevelHidden:)"))); +- (void)testTopLevelHiddenNested:(id)topLevelHiddenNested __attribute__((swift_name("test(topLevelHiddenNested:)"))); +- (void)testTopLevelHiddenNestedNested:(id)topLevelHiddenNestedNested __attribute__((swift_name("test(topLevelHiddenNestedNested:)"))); +- (void)testTopLevelHiddenNestedInner:(id)topLevelHiddenNestedInner __attribute__((swift_name("test(topLevelHiddenNestedInner:)"))); +- (void)testTopLevelHiddenInner:(id)topLevelHiddenInner __attribute__((swift_name("test(topLevelHiddenInner:)"))); +- (void)testTopLevelHiddenInnerInner:(id)topLevelHiddenInnerInner __attribute__((swift_name("test(topLevelHiddenInnerInner:)"))); +- (void)testExtendingHiddenNested:(id)extendingHiddenNested __attribute__((swift_name("test(extendingHiddenNested:)"))); +- (void)testExtendingNestedInHidden:(id)extendingNestedInHidden __attribute__((swift_name("test(extendingNestedInHidden:)"))); @property (readonly) id _Nullable errorVal __attribute__((swift_name("errorVal"))) __attribute__((unavailable("error"))); @property id _Nullable errorVar __attribute__((swift_name("errorVar"))) __attribute__((unavailable("error"))); @property (readonly) id _Nullable openErrorVal __attribute__((swift_name("openErrorVal"))) __attribute__((unavailable("error"))); @@ -681,6 +694,11 @@ __attribute__((swift_name("TestDeprecation.ExtendingHidden"))) @interface ValuesTestDeprecationExtendingHidden : NSObject @end; +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.ExtendingHiddenNested"))) +@interface ValuesTestDeprecationExtendingHiddenNested : NSObject +@end; + __attribute__((swift_name("TestDeprecationHiddenInterface"))) @protocol ValuesTestDeprecationHiddenInterface @required @@ -698,6 +716,35 @@ __attribute__((swift_name("TestDeprecation.Hidden"))) @interface ValuesTestDeprecationHidden : NSObject @end; +__attribute__((swift_name("TestDeprecation.HiddenNested"))) +@interface ValuesTestDeprecationHiddenNested : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.HiddenNestedNested"))) +@interface ValuesTestDeprecationHiddenNestedNested : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.HiddenNestedInner"))) +@interface ValuesTestDeprecationHiddenNestedInner : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.HiddenInner"))) +@interface ValuesTestDeprecationHiddenInner : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.HiddenInnerInner"))) +@interface ValuesTestDeprecationHiddenInnerInner : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TestDeprecation.ExtendingNestedInHidden"))) +@interface ValuesTestDeprecationExtendingNestedInHidden : NSObject +@end; + __attribute__((swift_name("TestDeprecation.OpenError"))) @interface ValuesTestDeprecationOpenError : ValuesTestDeprecation - (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer)) __attribute__((unavailable("error"))); @@ -859,6 +906,36 @@ __attribute__((swift_name("TestDeprecation.NormalOverride"))) @property id _Nullable openNormalVar __attribute__((swift_name("openNormalVar"))); @end; +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden"))) +@interface ValuesTopLevelHidden : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden.Nested"))) +@interface ValuesTopLevelHiddenNested : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden.NestedNested"))) +@interface ValuesTopLevelHiddenNestedNested : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden.NestedInner"))) +@interface ValuesTopLevelHiddenNestedInner : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden.Inner"))) +@interface ValuesTopLevelHiddenInner : NSObject +@end; + +__attribute__((objc_subclassing_restricted)) +__attribute__((swift_name("TopLevelHidden.InnerInner"))) +@interface ValuesTopLevelHiddenInnerInner : NSObject +@end; + @interface ValuesEnumeration (ValuesKt) - (ValuesEnumeration *)getAnswer __attribute__((swift_name("getAnswer()"))); @end; diff --git a/backend.native/tests/framework/values/values.kt b/backend.native/tests/framework/values/values.kt index e42aedb3ceb..bf2b07c9485 100644 --- a/backend.native/tests/framework/values/values.kt +++ b/backend.native/tests/framework/values/values.kt @@ -495,7 +495,9 @@ class TestInvalidIdentifiers { @Suppress("UNUSED_PARAMETER") open class TestDeprecation() { @Deprecated("hidden", level = DeprecationLevel.HIDDEN) open class OpenHidden : TestDeprecation() - @Suppress("DEPRECATION_ERROR") class ExtendingHidden : OpenHidden() + @Suppress("DEPRECATION_ERROR") class ExtendingHidden : OpenHidden() { + class Nested + } @Deprecated("hidden", level = DeprecationLevel.HIDDEN) interface HiddenInterface { fun effectivelyHidden(): Any @@ -508,7 +510,19 @@ open class TestDeprecation() { @Suppress("DEPRECATION_ERROR") fun callEffectivelyHidden(obj: Any): Int = (obj as HiddenInterface).effectivelyHidden() as Int - @Deprecated("hidden", level = DeprecationLevel.HIDDEN) class Hidden : TestDeprecation() + @Deprecated("hidden", level = DeprecationLevel.HIDDEN) class Hidden : TestDeprecation() { + open class Nested { + class Nested + inner class Inner + } + + inner class Inner { + inner class Inner + } + } + + @Suppress("DEPRECATION_ERROR") class ExtendingNestedInHidden : Hidden.Nested() + @Suppress("DEPRECATION_ERROR") fun getHidden() = Hidden() @Deprecated("hidden", level = DeprecationLevel.HIDDEN) constructor(hidden: Byte) : this() @@ -648,6 +662,34 @@ open class TestDeprecation() { override val openNormalVal: Any? = null override var openNormalVar: Any? = null } + + @Suppress("DEPRECATION_ERROR") fun test(hiddenNested: Hidden.Nested) {} + @Suppress("DEPRECATION_ERROR") fun test(hiddenNestedNested: Hidden.Nested.Nested) {} + @Suppress("DEPRECATION_ERROR") fun test(hiddenNestedInner: Hidden.Nested.Inner) {} + @Suppress("DEPRECATION_ERROR") fun test(hiddenInner: Hidden.Inner) {} + @Suppress("DEPRECATION_ERROR") fun test(hiddenInnerInner: Hidden.Inner.Inner) {} + + @Suppress("DEPRECATION_ERROR") fun test(topLevelHidden: TopLevelHidden) {} + @Suppress("DEPRECATION_ERROR") fun test(topLevelHiddenNested: TopLevelHidden.Nested) {} + @Suppress("DEPRECATION_ERROR") fun test(topLevelHiddenNestedNested: TopLevelHidden.Nested.Nested) {} + @Suppress("DEPRECATION_ERROR") fun test(topLevelHiddenNestedInner: TopLevelHidden.Nested.Inner) {} + @Suppress("DEPRECATION_ERROR") fun test(topLevelHiddenInner: TopLevelHidden.Inner) {} + @Suppress("DEPRECATION_ERROR") fun test(topLevelHiddenInnerInner: TopLevelHidden.Inner.Inner) {} + + @Suppress("DEPRECATION_ERROR") fun test(extendingHiddenNested: ExtendingHidden.Nested) {} + @Suppress("DEPRECATION_ERROR") fun test(extendingNestedInHidden: ExtendingNestedInHidden) {} + +} + +@Deprecated("hidden", level = DeprecationLevel.HIDDEN) class TopLevelHidden { + class Nested { + class Nested + inner class Inner + } + + inner class Inner { + inner class Inner + } } @Deprecated("hidden", level = DeprecationLevel.HIDDEN) fun hidden() {}