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 8371e775160..11723ee88a8 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
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.AsmUtil.*
import org.jetbrains.kotlin.codegen.StackValue.*
+import org.jetbrains.kotlin.codegen.intrinsics.JavaClassProperty
import org.jetbrains.kotlin.codegen.pseudoInsns.fixStackAndJump
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
@@ -819,6 +820,34 @@ class ExpressionCodegen(
return expression.onStack
}
+ override fun visitClassReference(expression: IrClassReference, data: BlockInfo): StackValue {
+ generateClassLiteralReference(expression, true, data)
+ return expression.onStack
+ }
+
+ fun generateClassLiteralReference(
+ receiverExpression: IrExpression,
+ wrapIntoKClass: Boolean,
+ data: BlockInfo
+ ) {
+ if (receiverExpression !is IrClassReference /* && DescriptorUtils.isObject(receiverExpression.descriptor)*/) {
+ JavaClassProperty.generateImpl(mv, gen(receiverExpression, data))
+ }
+ else {
+// if (TypeUtils.isTypeParameter(type)) {
+// assert(TypeUtils.isReifiedTypeParameter(type)) { "Non-reified type parameter under ::class should be rejected by type checker: " + type }
+// putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS)
+// }
+
+ putJavaLangClassInstance(mv, typeMapper.mapType(receiverExpression.descriptor.defaultType))
+ }
+
+ if (wrapIntoKClass) {
+ wrapJavaClassIntoKClass(mv)
+ }
+
+ }
+
private fun coerceNotToUnit(fromType: Type, toType: Type) {
if (toType != AsmTypes.UNIT_TYPE) {
coerce(fromType, toType, mv)
diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt
index a9a4403027c..bf545c06fb4 100644
--- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt
+++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt
@@ -18,57 +18,29 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
-import org.jetbrains.kotlin.codegen.AsmUtil.putJavaLangClassInstance
-import org.jetbrains.kotlin.codegen.AsmUtil.wrapJavaClassIntoKClass
-import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.ir.expressions.IrClassReference
+import org.jetbrains.kotlin.ir.expressions.IrGetClass
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
-import org.jetbrains.kotlin.psi.KtClassLiteralExpression
-import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS
-import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
-import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
-import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class KClassJavaProperty : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return object: IrIntrinsicFunction(expression, signature, context) {
override fun invoke(v: InstructionAdapter, codegen: org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen, data: BlockInfo): StackValue {
- putJavaLangClassInstance(v, signature.returnType)
- wrapJavaClassIntoKClass(v)
+ val extensionReceiver = expression.extensionReceiver
+ if (extensionReceiver is IrClassReference || extensionReceiver is IrGetClass) {
+ codegen.generateClassLiteralReference(extensionReceiver, false, data)
+ }
+ else {
+ codegen.gen(extensionReceiver!!, data)
+ val mapToCallableMethod = context.state.typeMapper.mapToCallableMethod(expression.descriptor as FunctionDescriptor, false)
+ mapToCallableMethod.genInvokeInstruction(codegen.mv)
+ }
return StackValue.onStack(signature.returnType)
}
}
-
-
-// val type = lhs.type
-// if (lhs is DoubleColonLHS.Expression && !(lhs as DoubleColonLHS.Expression).isObject) {
-// JavaClassProperty.generateImpl(v, gen(receiverExpression))
-// }
-// else {
-// if (TypeUtils.isTypeParameter(type)) {
-// assert(TypeUtils.isReifiedTypeParameter(type)) { "Non-reified type parameter under ::class should be rejected by type checker: " + type }
-// putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.JAVA_CLASS)
-// }
-
-// putJavaLangClassInstance(v, typeMapper.mapType(type))
-// }
-
-// if (wrapIntoKClass) {
-// wrapJavaClassIntoKClass(v)
-// }
-
-// return Unit
- }
-
-
- fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? {
- val receiverValue = resolvedCall!!.extensionReceiver as? ExpressionReceiver ?: return null
- val classLiteralExpression = receiverValue.expression as? KtClassLiteralExpression ?: return null
- val receiverExpression = classLiteralExpression.receiverExpression ?: return null
- val lhs = codegen.bindingContext.get(DOUBLE_COLON_LHS, receiverExpression) ?: return null
- val value = codegen.generateClassLiteralReference(lhs, receiverExpression, /* wrapIntoKClass = */ false)
- return StackValue.coercion(value, returnType)
}
}
diff --git a/compiler/testData/ir/irText/expressions/classReference.kt b/compiler/testData/ir/irText/expressions/classReference.kt
new file mode 100644
index 00000000000..4ba32de63e2
--- /dev/null
+++ b/compiler/testData/ir/irText/expressions/classReference.kt
@@ -0,0 +1,10 @@
+//WITH_RUNTIME
+class A
+
+fun test() {
+ A::class
+ A()::class
+
+ A::class.java
+ A()::class.java
+}
\ No newline at end of file
diff --git a/compiler/testData/ir/irText/expressions/classReference.txt b/compiler/testData/ir/irText/expressions/classReference.txt
new file mode 100644
index 00000000000..de35b64ab18
--- /dev/null
+++ b/compiler/testData/ir/irText/expressions/classReference.txt
@@ -0,0 +1,20 @@
+FILE /classReference.kt
+ CLASS CLASS A
+ CONSTRUCTOR public constructor A()
+ BLOCK_BODY
+ DELEGATING_CONSTRUCTOR_CALL 'constructor Any()'
+ INSTANCE_INITIALIZER_CALL classDescriptor='A'
+ FUN public fun test(): kotlin.Unit
+ BLOCK_BODY
+ TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
+ CLASS_REFERENCE 'A' type=kotlin.reflect.KClass
+ TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
+ GET_CLASS type=kotlin.reflect.KClass
+ CALL 'constructor A()' type=A origin=null
+ TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
+ CALL '() on KClass: Class' type=java.lang.Class origin=GET_PROPERTY
+ $receiver: CLASS_REFERENCE 'A' type=kotlin.reflect.KClass
+ TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
+ CALL '() on KClass: Class' type=java.lang.Class origin=GET_PROPERTY
+ $receiver: GET_CLASS type=kotlin.reflect.KClass
+ CALL 'constructor A()' type=A origin=null
diff --git a/compiler/testData/ir/irText/expressions/objectClassReference.kt b/compiler/testData/ir/irText/expressions/objectClassReference.kt
new file mode 100644
index 00000000000..c0d3efd9519
--- /dev/null
+++ b/compiler/testData/ir/irText/expressions/objectClassReference.kt
@@ -0,0 +1,7 @@
+//WITH_RUNTIME
+object A
+
+fun test() {
+ A::class
+ A::class.java
+}
\ No newline at end of file
diff --git a/compiler/testData/ir/irText/expressions/objectClassReference.txt b/compiler/testData/ir/irText/expressions/objectClassReference.txt
new file mode 100644
index 00000000000..ba6bc0771be
--- /dev/null
+++ b/compiler/testData/ir/irText/expressions/objectClassReference.txt
@@ -0,0 +1,13 @@
+FILE /objectClassReference.kt
+ CLASS OBJECT A
+ CONSTRUCTOR private constructor A()
+ BLOCK_BODY
+ DELEGATING_CONSTRUCTOR_CALL 'constructor Any()'
+ INSTANCE_INITIALIZER_CALL classDescriptor='A'
+ FUN public fun test(): kotlin.Unit
+ BLOCK_BODY
+ TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
+ CLASS_REFERENCE 'A' type=kotlin.reflect.KClass
+ TYPE_OP origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
+ CALL '() on KClass: Class' type=java.lang.Class origin=GET_PROPERTY
+ $receiver: CLASS_REFERENCE 'A' type=kotlin.reflect.KClass
diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java
index 46b99cd2060..33dd216478c 100644
--- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java
+++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java
@@ -400,6 +400,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName);
}
+ @TestMetadata("classReference.kt")
+ public void testClassReference() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/classReference.kt");
+ doTest(fileName);
+ }
+
@TestMetadata("coercionToUnit.kt")
public void testCoercionToUnit() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/coercionToUnit.kt");
@@ -520,6 +526,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName);
}
+ @TestMetadata("objectClassReference.kt")
+ public void testObjectClassReference() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/objectClassReference.kt");
+ doTest(fileName);
+ }
+
@TestMetadata("primitiveComparisons.kt")
public void testPrimitiveComparisons() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/primitiveComparisons.kt");