diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java index 20179736531..c09e4b3b19d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AsmUtil.java @@ -482,6 +482,10 @@ public class AsmUtil { DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration(); Visibility memberVisibility = memberDescriptor.getVisibility(); + if (JvmCodegenUtil.isNonIntrinsicPrivateCompanionObjectInInterface(memberDescriptor)) { + return ACC_PUBLIC; + } + if (memberDescriptor instanceof FunctionDescriptor && isInlineClassWrapperConstructor((FunctionDescriptor) memberDescriptor, kind)) { return ACC_PRIVATE; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index dc9b998bb5c..75671846c2f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -786,12 +786,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { state.getLanguageVersionSettings().supportsFeature(LanguageFeature.DeprecatedFieldForInvisibleCompanionObject); boolean properVisibilityForCompanionObjectInstanceField = state.getLanguageVersionSettings().supportsFeature(LanguageFeature.ProperVisibilityForCompanionObjectInstanceField); + boolean hasPrivateOrProtectedProperVisibility = (properFieldVisibilityFlag & (ACC_PRIVATE | ACC_PROTECTED)) != 0; + boolean hasPackagePrivateProperVisibility = (properFieldVisibilityFlag & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)) == 0; boolean fieldShouldBeDeprecated = deprecatedFieldForInvisibleCompanionObject && !properVisibilityForCompanionObjectInstanceField && - (properFieldVisibilityFlag & (ACC_PRIVATE | ACC_PROTECTED)) != 0; + (hasPrivateOrProtectedProperVisibility || hasPackagePrivateProperVisibility || + isNonIntrinsicPrivateCompanionObjectInInterface(companionObjectDescriptor)); boolean doNotGeneratePublic = - properVisibilityForCompanionObjectInstanceField && (properFieldVisibilityFlag & (ACC_PRIVATE | ACC_PROTECTED)) != 0; + properVisibilityForCompanionObjectInstanceField && hasPrivateOrProtectedProperVisibility; int fieldAccessFlags; if (doNotGeneratePublic) { fieldAccessFlags = ACC_STATIC | ACC_FINAL; @@ -805,6 +808,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (fieldShouldBeDeprecated) { fieldAccessFlags |= ACC_DEPRECATED; } + if (properVisibilityForCompanionObjectInstanceField && + JvmCodegenUtil.isCompanionObjectInInterfaceNotIntrinsic(companionObjectDescriptor) && + Visibilities.isPrivate(companionObjectDescriptor.getVisibility())) { + fieldAccessFlags |= ACC_SYNTHETIC; + } StackValue.Field field = StackValue.singleton(companionObjectDescriptor, typeMapper); FieldVisitor fv = v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject == null ? myClass.getPsiOrParent() : companionObject), fieldAccessFlags, field.name, field.type.getDescriptor(), null, null); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java index 190ad464c04..3826c72f3f1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmCodegenUtil.java @@ -348,6 +348,11 @@ public class JvmCodegenUtil { !JvmAbi.isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject); } + public static boolean isNonIntrinsicPrivateCompanionObjectInInterface(@NotNull DeclarationDescriptorWithVisibility companionObject) { + return isCompanionObjectInInterfaceNotIntrinsic(companionObject) && + Visibilities.isPrivate(companionObject.getVisibility()); + } + public static boolean isDeclarationOfBigArityFunctionInvoke(@Nullable DeclarationDescriptor descriptor) { return descriptor instanceof FunctionInvokeDescriptor && ((FunctionInvokeDescriptor) descriptor).hasBigArity(); } diff --git a/compiler/testData/codegen/box/objects/companionObjectAccess/kt27121.kt b/compiler/testData/codegen/box/objects/companionObjectAccess/kt27121.kt new file mode 100644 index 00000000000..5023ab02a25 --- /dev/null +++ b/compiler/testData/codegen/box/objects/companionObjectAccess/kt27121.kt @@ -0,0 +1,14 @@ +// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField +// IGNORE_BACKEND: JS, JS_IR, JVM_IR + +interface A { + fun test() = ok() + + private companion object { + fun ok() = "OK" + } +} + +class C : A + +fun box() = C().test() diff --git a/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_after.kt b/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_after.kt new file mode 100644 index 00000000000..b4bfd809bc9 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_after.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: +ProperVisibilityForCompanionObjectInstanceField + +open class TestProtectedCompanionInClass { + protected companion object +} + +class TestInternalCompanionInClass { + internal companion object +} + +class TestPrivateCompanionInClass { + private companion object +} + +interface TestPrivateCompanionInInterface { + private companion object +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_after.txt b/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_after.txt new file mode 100644 index 00000000000..f27d67b748c --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_after.txt @@ -0,0 +1,59 @@ +@kotlin.Metadata +public final class TestInternalCompanionInClass$Companion { + inner class TestInternalCompanionInClass$Companion + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public final class TestInternalCompanionInClass { + public final static field Companion: TestInternalCompanionInClass$Companion + inner class TestInternalCompanionInClass$Companion + static method (): void + public method (): void +} + +@kotlin.Metadata +final class TestPrivateCompanionInClass$Companion { + inner class TestPrivateCompanionInClass$Companion + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public final class TestPrivateCompanionInClass { + private final static field Companion: TestPrivateCompanionInClass$Companion + inner class TestPrivateCompanionInClass$Companion + static method (): void + public method (): void +} + +@kotlin.Metadata +final class TestPrivateCompanionInInterface$Companion { + synthetic final static field $$INSTANCE: TestPrivateCompanionInInterface$Companion + inner class TestPrivateCompanionInInterface$Companion + static method (): void + private method (): void +} + +@kotlin.Metadata +public interface TestPrivateCompanionInInterface { + public synthetic final static field Companion: TestPrivateCompanionInInterface$Companion + inner class TestPrivateCompanionInInterface$Companion + static method (): void +} + +@kotlin.Metadata +public final class TestProtectedCompanionInClass$Companion { + inner class TestProtectedCompanionInClass$Companion + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public class TestProtectedCompanionInClass { + protected final static field Companion: TestProtectedCompanionInClass$Companion + inner class TestProtectedCompanionInClass$Companion + static method (): void + public method (): void +} diff --git a/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_before.kt b/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_before.kt new file mode 100644 index 00000000000..8e91d07b7a3 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_before.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: -ProperVisibilityForCompanionObjectInstanceField + +open class TestProtectedCompanionInClass { + protected companion object +} + +class TestInternalCompanionInClass { + internal companion object +} + +class TestPrivateCompanionInClass { + private companion object +} + +interface TestPrivateCompanionInInterface { + private companion object +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_before.txt b/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_before.txt new file mode 100644 index 00000000000..f5e9dbd9a1c --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/companionObjectVisibility_before.txt @@ -0,0 +1,59 @@ +@kotlin.Metadata +public final class TestInternalCompanionInClass$Companion { + inner class TestInternalCompanionInClass$Companion + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public final class TestInternalCompanionInClass { + public final static field Companion: TestInternalCompanionInClass$Companion + inner class TestInternalCompanionInClass$Companion + static method (): void + public method (): void +} + +@kotlin.Metadata +final class TestPrivateCompanionInClass$Companion { + inner class TestPrivateCompanionInClass$Companion + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public final class TestPrivateCompanionInClass { + public deprecated final static @java.lang.Deprecated field Companion: TestPrivateCompanionInClass$Companion + inner class TestPrivateCompanionInClass$Companion + static method (): void + public method (): void +} + +@kotlin.Metadata +final class TestPrivateCompanionInInterface$Companion { + synthetic final static field $$INSTANCE: TestPrivateCompanionInInterface$Companion + inner class TestPrivateCompanionInInterface$Companion + static method (): void + private method (): void +} + +@kotlin.Metadata +public interface TestPrivateCompanionInInterface { + public deprecated final static @java.lang.Deprecated field Companion: TestPrivateCompanionInInterface$Companion + inner class TestPrivateCompanionInInterface$Companion + static method (): void +} + +@kotlin.Metadata +public final class TestProtectedCompanionInClass$Companion { + inner class TestProtectedCompanionInClass$Companion + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void +} + +@kotlin.Metadata +public class TestProtectedCompanionInClass { + public deprecated final static @java.lang.Deprecated field Companion: TestProtectedCompanionInClass$Companion + inner class TestProtectedCompanionInClass$Companion + static method (): void + public method (): void +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 1dab25ad1d0..8ce91b75542 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -15123,6 +15123,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27117.kt"); } + @TestMetadata("kt27121.kt") + public void testKt27121() throws Exception { + runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27121.kt"); + } + @TestMetadata("privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt") public void testPrivateCompanionObjectAccessedFromAnonymousObjectInNestedClass() throws Exception { runTest("compiler/testData/codegen/box/objects/companionObjectAccess/privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 5178b0baa6f..31ceba6509f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -38,6 +38,16 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { runTest("compiler/testData/codegen/bytecodeListing/callableNameIntrinsic.kt"); } + @TestMetadata("companionObjectVisibility_after.kt") + public void testCompanionObjectVisibility_after() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/companionObjectVisibility_after.kt"); + } + + @TestMetadata("companionObjectVisibility_before.kt") + public void testCompanionObjectVisibility_before() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/companionObjectVisibility_before.kt"); + } + @TestMetadata("coroutineContextIntrinsic.kt") public void testCoroutineContextIntrinsic_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/bytecodeListing/coroutineContextIntrinsic.kt", "kotlin.coroutines.experimental"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 12a26348210..872f3318688 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -15123,6 +15123,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27117.kt"); } + @TestMetadata("kt27121.kt") + public void testKt27121() throws Exception { + runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27121.kt"); + } + @TestMetadata("privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt") public void testPrivateCompanionObjectAccessedFromAnonymousObjectInNestedClass() throws Exception { runTest("compiler/testData/codegen/box/objects/companionObjectAccess/privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 5a4785ef02a..e98f2d61d68 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -15128,6 +15128,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27117.kt"); } + @TestMetadata("kt27121.kt") + public void testKt27121() throws Exception { + runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27121.kt"); + } + @TestMetadata("privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt") public void testPrivateCompanionObjectAccessedFromAnonymousObjectInNestedClass() throws Exception { runTest("compiler/testData/codegen/box/objects/companionObjectAccess/privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java index fb982cbc167..542c9cc0677 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java @@ -13308,6 +13308,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27117.kt"); } + @TestMetadata("kt27121.kt") + public void testKt27121() throws Exception { + runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27121.kt"); + } + @TestMetadata("privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt") public void testPrivateCompanionObjectAccessedFromAnonymousObjectInNestedClass() throws Exception { runTest("compiler/testData/codegen/box/objects/companionObjectAccess/privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 057bb6c5c09..5882b491f3e 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -14353,6 +14353,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27117.kt"); } + @TestMetadata("kt27121.kt") + public void testKt27121() throws Exception { + runTest("compiler/testData/codegen/box/objects/companionObjectAccess/kt27121.kt"); + } + @TestMetadata("privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt") public void testPrivateCompanionObjectAccessedFromAnonymousObjectInNestedClass() throws Exception { runTest("compiler/testData/codegen/box/objects/companionObjectAccess/privateCompanionObjectAccessedFromAnonymousObjectInNestedClass.kt");