diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 8f787d5a445..5a7e8cfc973 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -14366,6 +14366,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt"); } + @TestMetadata("protectedField.kt") + public void testProtectedField() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt"); + } + @TestMetadata("samUnboundTypeParameter.kt") public void testSamUnboundTypeParameter() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index d089117a873..573fa4da38d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -14,8 +14,6 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.intrinsics.receiverAndArgs import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator -import org.jetbrains.kotlin.backend.jvm.ir.hasJvmDefault -import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault import org.jetbrains.kotlin.backend.jvm.ir.isLambda import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledParameters import org.jetbrains.kotlin.codegen.syntheticAccessorToSuperSuffix @@ -75,8 +73,8 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle } private val functionMap = mutableMapOf, IrFunctionSymbol>() - private val getterMap = mutableMapOf() - private val setterMap = mutableMapOf() + private val getterMap = mutableMapOf, IrSimpleFunctionSymbol>() + private val setterMap = mutableMapOf, IrSimpleFunctionSymbol>() override fun visitFunctionAccess(expression: IrFunctionAccessExpression): IrExpression { if (expression.usesDefaultArguments()) { @@ -155,21 +153,46 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle return super.visitExpression(modifyFunctionAccessExpression(expression, accessor)) } - override fun visitGetField(expression: IrGetField) = super.visitExpression( - if (!expression.symbol.isAccessible(false, expression.receiver?.type?.classifierOrNull as? IrClassSymbol)) { - modifyGetterExpression(expression, getterMap.getOrPut(expression.symbol) { makeGetterAccessorSymbol(expression.symbol) }) - } else { - expression - } - ) + override fun visitGetField(expression: IrGetField): IrExpression { + val dispatchReceiverType = expression.receiver?.type + return super.visitExpression( + if (!expression.symbol.isAccessible(false, dispatchReceiverType?.classifierOrNull as? IrClassSymbol)) { + val symbol = expression.symbol + val parent = + symbol.owner.accessorParent(dispatchReceiverType?.classOrNull?.owner ?: symbol.owner.parent) as IrClass + val symbolToAccess = symbol.owner.findDescendantIn(parent)?.symbol ?: symbol + modifyGetterExpression( + expression, + getterMap.getOrPut(Pair(symbolToAccess, parent)) { makeGetterAccessorSymbol(symbolToAccess, parent) } + ) + } else { + expression + } + ) + } - override fun visitSetField(expression: IrSetField) = super.visitExpression( - if (!expression.symbol.isAccessible(false, expression.receiver?.type?.classifierOrNull as? IrClassSymbol)) { - modifySetterExpression(expression, setterMap.getOrPut(expression.symbol) { makeSetterAccessorSymbol(expression.symbol) }) - } else { - expression + override fun visitSetField(expression: IrSetField): IrExpression { + val dispatchReceiverType = expression.receiver?.type + return super.visitExpression( + if (!expression.symbol.isAccessible(false, dispatchReceiverType?.classifierOrNull as? IrClassSymbol)) { + val symbol = expression.symbol + val parent = + symbol.owner.accessorParent(dispatchReceiverType?.classOrNull?.owner ?: symbol.owner.parent) as IrClass + val symbolToAccess = symbol.owner.findDescendantIn(parent)?.symbol ?: symbol + modifySetterExpression( + expression, + setterMap.getOrPut(Pair(symbolToAccess, parent)) { makeSetterAccessorSymbol(symbolToAccess, parent) } + ) + } else { + expression + } + ) + } + + private fun IrField.findDescendantIn(derivedClass: IrClass): IrField? = + derivedClass.fields.singleOrNull { candidate -> + candidate.name == this.name && candidate.overrides(this) } - ) override fun visitConstructor(declaration: IrConstructor): IrStatement { if (declaration.isOrShouldBeHidden) { @@ -303,7 +326,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle copyAllParamsToArgs(it, accessor) } - private fun makeGetterAccessorSymbol(fieldSymbol: IrFieldSymbol): IrSimpleFunctionSymbol = + private fun makeGetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrDeclarationParent): IrSimpleFunctionSymbol = buildFun { origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR name = fieldSymbol.owner.accessorNameForGetter() @@ -311,7 +334,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle modality = Modality.FINAL returnType = fieldSymbol.owner.type }.also { accessor -> - accessor.parent = fieldSymbol.owner.accessorParent() + accessor.parent = parent pendingAccessorsToAdd.add(accessor) if (!fieldSymbol.owner.isStatic) { @@ -339,7 +362,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle ) } - private fun makeSetterAccessorSymbol(fieldSymbol: IrFieldSymbol): IrSimpleFunctionSymbol = + private fun makeSetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrDeclarationParent): IrSimpleFunctionSymbol = buildFun { origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR name = fieldSymbol.owner.accessorNameForSetter() @@ -347,7 +370,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle modality = Modality.FINAL returnType = context.irBuiltIns.unitType }.also { accessor -> - accessor.parent = fieldSymbol.owner.accessorParent() + accessor.parent = parent pendingAccessorsToAdd.add(accessor) if (!fieldSymbol.owner.isStatic) { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt index 496b052254a..394f7330e5b 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/AdditionalIrUtils.kt @@ -79,6 +79,18 @@ fun IrSimpleFunction.overrides(other: IrSimpleFunction): Boolean { return false } +fun IrField.overrides(other: IrField): Boolean { + if (this == other) return true + + this.overriddenSymbols.forEach { + if (it.owner.overrides(other)) { + return true + } + } + + return false +} + private val IrConstructorCall.annotationClass get() = this.symbol.owner.constructedClass diff --git a/compiler/testData/codegen/box/javaInterop/protectedField.kt b/compiler/testData/codegen/box/javaInterop/protectedField.kt new file mode 100644 index 00000000000..8b4ed955a5c --- /dev/null +++ b/compiler/testData/codegen/box/javaInterop/protectedField.kt @@ -0,0 +1,23 @@ +// TARGET_BACKEND: JVM +// IGNORE_BACKEND_FIR: JVM_IR +// FILE: ProtectedField.java + +public abstract class ProtectedField { + protected String field = "fail"; +} + +//FILE: test.kt +package test + +import ProtectedField + +class Derived: ProtectedField() { + fun setAndGetField(arg: String) = myRun { + super.field = arg + super.field + } +} + +fun myRun(f: () -> String) = f() + +fun box() = Derived().setAndGetField("OK") diff --git a/compiler/testData/codegen/box/statics/inlineCallsStaticMethod.kt b/compiler/testData/codegen/box/statics/inlineCallsStaticMethod.kt index d49599766b2..10ccf7c87b8 100644 --- a/compiler/testData/codegen/box/statics/inlineCallsStaticMethod.kt +++ b/compiler/testData/codegen/box/statics/inlineCallsStaticMethod.kt @@ -1,5 +1,4 @@ // !LANGUAGE: -ProhibitProtectedCallFromInline -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // FILE: Test.java diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index b55a5cb6774..49aa967a48a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -15581,6 +15581,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt"); } + @TestMetadata("protectedField.kt") + public void testProtectedField() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt"); + } + @TestMetadata("samUnboundTypeParameter.kt") public void testSamUnboundTypeParameter() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index fd5e8dda73a..8fba91469a5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -15581,6 +15581,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt"); } + @TestMetadata("protectedField.kt") + public void testProtectedField() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt"); + } + @TestMetadata("samUnboundTypeParameter.kt") public void testSamUnboundTypeParameter() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 7e6fb635db5..417f855c944 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -14366,6 +14366,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/javaInterop/lambdaInstanceOf.kt"); } + @TestMetadata("protectedField.kt") + public void testProtectedField() throws Exception { + runTest("compiler/testData/codegen/box/javaInterop/protectedField.kt"); + } + @TestMetadata("samUnboundTypeParameter.kt") public void testSamUnboundTypeParameter() throws Exception { runTest("compiler/testData/codegen/box/javaInterop/samUnboundTypeParameter.kt");