diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 3f69c102b3a..ab41066b55d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -540,11 +540,23 @@ class ExpressionCodegen( val fieldName = realField.name.asString() val isStatic = expression.receiver == null expression.markLineNumber(startOffset = true) - val ownerName = expression.receiver?.let { receiver -> - val ownerType = typeMapper.mapTypeAsDeclaration(receiver.type) + + val ownerType = when { + expression.superQualifierSymbol != null -> { + typeMapper.mapClass(expression.superQualifierSymbol!!.owner) + } + expression.receiver != null -> { + typeMapper.mapTypeAsDeclaration(expression.receiver!!.type) + } + else -> typeMapper.mapClass(callee.parentAsClass) + } + + val ownerName = ownerType.internalName + + expression.receiver?.let { receiver -> receiver.accept(this, data).materializeAt(ownerType, receiver.type) - ownerType.internalName - } ?: typeMapper.mapClass(callee.parentAsClass).internalName + } + return if (expression is IrSetField) { val value = expression.value.accept(this, data) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt index dc8dd80a004..37e3d6f4c70 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt @@ -77,6 +77,18 @@ val PropertyDescriptor.unwrappedGetMethod: FunctionDescriptor? val PropertyDescriptor.unwrappedSetMethod: FunctionDescriptor? get() = if (this is SyntheticPropertyDescriptor) this.setMethod else setter +// Only works for descriptors of Java fields. +internal fun PropertyDescriptor.resolveFakeOverride(): PropertyDescriptor { + assert(getter == null) + // Fields can only be inherited from objects, so there will be at most one overridden descriptor at each step. + var current = this + while (current.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + current = current.overriddenDescriptors.singleOrNull() + ?: error("Descriptor of Java field $current should have exactly one overridden descriptor, have ${current.overriddenDescriptors}") + } + return current +} + val KtPureElement?.pureStartOffsetOrUndefined get() = this?.psiOrParent?.startOffsetSkippingComments ?: UNDEFINED_OFFSET val KtPureElement?.pureEndOffsetOrUndefined get() = this?.psiOrParent?.endOffset ?: UNDEFINED_OFFSET diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt index 656fe11cde8..ceb7d33b528 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments import org.jetbrains.kotlin.psi2ir.intermediate.* +import org.jetbrains.kotlin.psi2ir.resolveFakeOverride import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod import org.jetbrains.kotlin.psi2ir.unwrappedSetMethod import org.jetbrains.kotlin.resolve.BindingContext @@ -309,7 +310,6 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen origin: IrStatementOrigin?, superQualifier: ClassDescriptor? ): PropertyLValueBase { - val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) } val unwrappedPropertyDescriptor = descriptor.unwrapPropertyDescriptor() val getterDescriptor = unwrappedPropertyDescriptor.unwrappedGetMethod @@ -320,6 +320,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen val propertyIrType = descriptor.type.toIrType() return if (getterSymbol != null || setterSymbol != null) { + val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) } val typeArgumentsList = typeArgumentsMap?.let { typeArguments -> descriptor.original.typeParameters.map { typeArguments[it]!!.toIrType() } @@ -341,17 +342,20 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen propertyReceiver, superQualifierSymbol ) - } else + } else { + val superQualifierSymbol = (superQualifier + ?: unwrappedPropertyDescriptor.containingDeclaration as? ClassDescriptor)?.let { context.symbolTable.referenceClass(it) } FieldPropertyLValue( context, scope, ktExpression.startOffsetSkippingComments, ktExpression.endOffset, origin, - context.symbolTable.referenceField(unwrappedPropertyDescriptor.original), + context.symbolTable.referenceField(unwrappedPropertyDescriptor.resolveFakeOverride().original), unwrappedPropertyDescriptor, propertyIrType, propertyReceiver, superQualifierSymbol ) + } } private fun generateArrayAccessAssignmentReceiver( diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index 964680664ed..255ac18a3f7 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments import org.jetbrains.kotlin.psi2ir.intermediate.* +import org.jetbrains.kotlin.psi2ir.resolveFakeOverride import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument @@ -174,11 +175,13 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator call: CallBuilder ): IrExpression { val getMethodDescriptor = descriptor.unwrappedGetMethod - val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) } val irType = descriptor.type.toIrType() return if (getMethodDescriptor == null) { call.callReceiver.call { dispatchReceiverValue, _ -> + val superQualifierSymbol = (call.superQualifier ?: descriptor.containingDeclaration as? ClassDescriptor)?.let { + context.symbolTable.referenceClass(it) + } val fieldSymbol = context.symbolTable.referenceField(descriptor.resolveFakeOverride().original) IrGetFieldImpl( startOffset, endOffset, @@ -190,6 +193,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator ).also { context.callToSubstitutedDescriptorMap[it] = descriptor } } } else { + val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) } call.callReceiver.adjustForCallee(getMethodDescriptor).call { dispatchReceiverValue, extensionReceiverValue -> if (descriptor.isDynamic()) { val dispatchReceiver = getDynamicExpressionReceiver(dispatchReceiverValue, extensionReceiverValue, descriptor) @@ -416,14 +420,3 @@ fun CallGenerator.generateCall(ktElement: KtElement, call: CallBuilder, origin: fun CallGenerator.generateCall(irExpression: IrExpression, call: CallBuilder, origin: IrStatementOrigin? = null) = generateCall(irExpression.startOffset, irExpression.endOffset, call, origin) - -// Only works for descriptors of Java fields. -private fun PropertyDescriptor.resolveFakeOverride(): PropertyDescriptor { - assert(getter == null) - // Fields can only be inherited from objects, so there will be at most one overridden descriptor at each step. - var current = this - while (current.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { - current = current.overriddenDescriptors.single() - } - return current -} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/javaStatics.kt b/compiler/testData/codegen/bytecodeText/javaStatics.kt index 1d0d0824b41..112c6ed69ba 100644 --- a/compiler/testData/codegen/bytecodeText/javaStatics.kt +++ b/compiler/testData/codegen/bytecodeText/javaStatics.kt @@ -20,25 +20,35 @@ class Parent { fun test() { Parent.a + Parent.a = 11 Parent.b + Parent.b = 22 Parent.foo() Parent.baz() Child.a + Child.a = 33 Child.b + Child.b = 44 Child.c + Child.c = 55 Child.foo() Child.bar() Child.baz() } // 1 GETSTATIC Parent.a : I +// 1 PUTSTATIC Parent.a : I // 1 GETSTATIC Parent.b : I +// 1 PUTSTATIC Parent.b : I // 1 INVOKESTATIC Parent.foo() // 1 INVOKESTATIC Parent.baz() // 1 GETSTATIC Child.a : I +// 1 PUTSTATIC Child.a : I // 1 GETSTATIC Child.b : I +// 1 PUTSTATIC Child.b : I // 1 GETSTATIC Child.c : I +// 1 PUTSTATIC Child.c : I // 1 INVOKESTATIC Child.foo() // 1 INVOKESTATIC Child.bar() // 1 INVOKESTATIC Child.baz()