[JVM IR] Added null-checks of handler for non-super $default calls
This commit is contained in:
committed by
Alexander Udalov
parent
fe50bb4b93
commit
c1d350f8f3
+16
-3
@@ -54,8 +54,9 @@ open class DefaultArgumentStubGenerator(
|
||||
|
||||
private fun lower(irFunction: IrFunction): List<IrFunction>? {
|
||||
val visibility = defaultArgumentStubVisibility(irFunction)
|
||||
val newIrFunction = irFunction.generateDefaultsFunction(context, skipInlineMethods, skipExternalMethods, forceSetOverrideSymbols, visibility)
|
||||
?: return null
|
||||
val newIrFunction =
|
||||
irFunction.generateDefaultsFunction(context, skipInlineMethods, skipExternalMethods, forceSetOverrideSymbols, visibility)
|
||||
?: return null
|
||||
if (newIrFunction.origin == IrDeclarationOrigin.FAKE_OVERRIDE) {
|
||||
return listOf(irFunction, newIrFunction)
|
||||
}
|
||||
@@ -90,6 +91,8 @@ open class DefaultArgumentStubGenerator(
|
||||
newIrFunction.valueParameters[it.index]
|
||||
}
|
||||
|
||||
generateSuperCallHandlerCheckIfNeeded(irFunction, newIrFunction)
|
||||
|
||||
var sourceParameterIndex = -1
|
||||
for (valueParameter in irFunction.valueParameters) {
|
||||
if (!valueParameter.isMovedReceiver()) {
|
||||
@@ -180,6 +183,12 @@ open class DefaultArgumentStubGenerator(
|
||||
} else dispatchCall
|
||||
}
|
||||
|
||||
protected open fun IrBlockBodyBuilder.generateSuperCallHandlerCheckIfNeeded(
|
||||
irFunction: IrFunction,
|
||||
newIrFunction: IrFunction) {
|
||||
//NO-OP Stub
|
||||
}
|
||||
|
||||
protected open fun needSpecialDispatch(irFunction: IrSimpleFunction) = false
|
||||
protected open fun IrBlockBodyBuilder.generateHandleCall(
|
||||
handlerDeclaration: IrValueParameter,
|
||||
@@ -506,7 +515,11 @@ private fun IrFunction.generateDefaultsFunctionImpl(
|
||||
val markerType = context.ir.symbols.defaultConstructorMarker.defaultType.makeNullable()
|
||||
newFunction.addValueParameter("marker".synthesizedString, markerType, IrDeclarationOrigin.DEFAULT_CONSTRUCTOR_MARKER)
|
||||
} else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
|
||||
newFunction.addValueParameter("handler".synthesizedString, context.irBuiltIns.anyNType, IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION)
|
||||
newFunction.addValueParameter(
|
||||
"handler".synthesizedString,
|
||||
context.irBuiltIns.anyNType,
|
||||
IrDeclarationOrigin.METHOD_HANDLER_IN_DEFAULT_FUNCTION
|
||||
)
|
||||
}
|
||||
|
||||
// TODO some annotations are needed (e.g. @JvmStatic), others need different values (e.g. @JvmName), the rest are redundant.
|
||||
|
||||
@@ -72,12 +72,16 @@ class JvmSymbols(
|
||||
override val ThrowTypeCastException: IrFunctionSymbol =
|
||||
typeCastExceptionClass.constructors.single()
|
||||
|
||||
val unsupportedOperationExceptionClass: IrClassSymbol = createClass(FqName("java.lang.UnsupportedOperationException")) { klass ->
|
||||
private val unsupportedOperationExceptionClass: IrClassSymbol = createClass(FqName("java.lang.UnsupportedOperationException")) { klass ->
|
||||
klass.addConstructor().apply {
|
||||
addValueParameter("message", irBuiltIns.stringType.makeNullable())
|
||||
}
|
||||
}
|
||||
|
||||
val ThrowUnsupportOperationExceptionClass: IrFunctionSymbol =
|
||||
unsupportedOperationExceptionClass.constructors.single()
|
||||
|
||||
|
||||
private fun createPackage(fqName: FqName): IrPackageFragment =
|
||||
IrExternalPackageFragmentImpl(IrExternalPackageFragmentSymbolImpl(EmptyPackageFragmentDescriptor(context.state.module, fqName)))
|
||||
|
||||
|
||||
+1
-3
@@ -87,9 +87,7 @@ private class CollectionStubMethodLowering(val context: JvmBackendContext) : Cla
|
||||
body = context.createIrBuilder(function.symbol).irBlockBody {
|
||||
+irThrow(
|
||||
irCall(
|
||||
this@CollectionStubMethodLowering.context.ir.symbols.unsupportedOperationExceptionClass.owner.constructors.single {
|
||||
it.valueParameters.size == 1 && it.valueParameters.single().type.isNullableString()
|
||||
}
|
||||
this@CollectionStubMethodLowering.context.ir.symbols.ThrowUnsupportOperationExceptionClass
|
||||
).apply {
|
||||
putValueArgument(0, irString("Operation is not supported for read-only collection"))
|
||||
}
|
||||
|
||||
+30
-6
@@ -5,17 +5,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.isFinalClass
|
||||
import org.jetbrains.kotlin.backend.common.lower.DefaultArgumentStubGenerator
|
||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||
import org.jetbrains.kotlin.backend.common.lower.irNot
|
||||
import org.jetbrains.kotlin.backend.common.lower.irThrow
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.getJvmVisibilityOfDefaultArgumentStub
|
||||
import org.jetbrains.kotlin.ir.builders.IrBlockBodyBuilder
|
||||
import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.builders.irGet
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.util.isTopLevelDeclaration
|
||||
|
||||
class JvmDefaultArgumentStubGenerator(override val context: JvmBackendContext) : DefaultArgumentStubGenerator(context, false, false) {
|
||||
override fun IrBlockBodyBuilder.selectArgumentOrDefault(
|
||||
@@ -47,4 +47,28 @@ class JvmDefaultArgumentStubGenerator(override val context: JvmBackendContext) :
|
||||
}
|
||||
|
||||
override fun defaultArgumentStubVisibility(function: IrFunction) = function.getJvmVisibilityOfDefaultArgumentStub()
|
||||
|
||||
override fun IrBlockBodyBuilder.generateSuperCallHandlerCheckIfNeeded(
|
||||
irFunction: IrFunction,
|
||||
newIrFunction: IrFunction
|
||||
) {
|
||||
if (irFunction !is IrSimpleFunction
|
||||
|| !this@JvmDefaultArgumentStubGenerator.context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()
|
||||
|| irFunction.isTopLevelDeclaration
|
||||
|| (irFunction.parent as? IrClass)?.isFinalClass == true
|
||||
)
|
||||
return
|
||||
|
||||
val handlerDeclaration = newIrFunction.valueParameters.last()
|
||||
+irIfThen(
|
||||
context.irBuiltIns.unitType,
|
||||
irNot(irEqualsNull(irGet(handlerDeclaration))),
|
||||
irThrow(irCall(this@JvmDefaultArgumentStubGenerator.context.ir.symbols.ThrowUnsupportOperationExceptionClass).apply {
|
||||
putValueArgument(
|
||||
0,
|
||||
irString("Super calls with default arguments not supported in this target, function: ${irFunction.name.asString()}")
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
open class O {
|
||||
open fun foo(s: String = throw Error("Fail: this expression should not be evaluated")) {}
|
||||
}
|
||||
|
||||
fun box(): String = try {
|
||||
val f = O::class.java.declaredMethods.single { it.name == "foo\$default" }
|
||||
f(null, O(), "s", 1, "non-null")
|
||||
"Fail: exception should have been thrown"
|
||||
} catch (e: Exception) {
|
||||
val cause = e.cause
|
||||
if (cause is UnsupportedOperationException) {
|
||||
"OK"
|
||||
} else {
|
||||
cause.toString()
|
||||
}
|
||||
}
|
||||
-3
@@ -1,6 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TODO KT-36771 Missing special code for super calls to inline functions support in JVM_IR
|
||||
|
||||
//open modality to method handle check generation
|
||||
open class A {
|
||||
inline fun test(p: String = "OK"): String {
|
||||
|
||||
+5
@@ -9369,6 +9369,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/superCallCheck.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("superCallHandlerOrder.kt")
|
||||
public void testSuperCallHandlerOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/superCallHandlerOrder.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("useNextParamInLambda.kt")
|
||||
public void testUseNextParamInLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/useNextParamInLambda.kt");
|
||||
|
||||
+5
@@ -9369,6 +9369,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/superCallCheck.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("superCallHandlerOrder.kt")
|
||||
public void testSuperCallHandlerOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/superCallHandlerOrder.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("useNextParamInLambda.kt")
|
||||
public void testUseNextParamInLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/useNextParamInLambda.kt");
|
||||
|
||||
+5
@@ -8239,6 +8239,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/superCallCheck.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("superCallHandlerOrder.kt")
|
||||
public void testSuperCallHandlerOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/superCallHandlerOrder.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("useNextParamInLambda.kt")
|
||||
public void testUseNextParamInLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/useNextParamInLambda.kt");
|
||||
|
||||
+5
@@ -8239,6 +8239,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/superCallCheck.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("superCallHandlerOrder.kt")
|
||||
public void testSuperCallHandlerOrder() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/superCallHandlerOrder.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("useNextParamInLambda.kt")
|
||||
public void testUseNextParamInLambda() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/defaultArguments/useNextParamInLambda.kt");
|
||||
|
||||
Reference in New Issue
Block a user