From ad88c60fd875a4283ebee61c2191b8e5eb2ee2b3 Mon Sep 17 00:00:00 2001 From: Mads Ager Date: Wed, 14 Oct 2020 14:46:55 +0200 Subject: [PATCH] [JVM_IR] Copy offsets from the original function to invokeSuspend. Otherwise, implicit returns in void returning suspend functions will not have the line number of the end brace. Fixes KT-41962 and KT-40464. --- .../builders/declarations/declarationBuilders.kt | 7 ++++++- .../backend/jvm/lower/AddContinuationLowering.kt | 2 +- .../backend/jvm/lower/SuspendLambdaLowering.kt | 12 ++++++++---- .../stepOver/coroutines/sequenceNested.out | 1 - .../stepOver/coroutines/sequenceNested2.ir.out | 14 ++++++++++++++ .../stepOver/coroutines/sequenceNested2.out | 1 - .../stepOver/coroutines/sequenceSimple.out | 1 - .../stepOver/soSuspendableCallInEndOfFun.out | 1 - 8 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested2.ir.out diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/declarations/declarationBuilders.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/declarations/declarationBuilders.kt index 6b96db00675..eacfd3de7f5 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/declarations/declarationBuilders.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/ir/builders/declarations/declarationBuilders.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.builders.declarations import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction @@ -168,9 +169,13 @@ fun IrClass.addFunction( isStatic: Boolean = false, isSuspend: Boolean = false, isFakeOverride: Boolean = false, - origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED + origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED, + startOffset: Int = UNDEFINED_OFFSET, + endOffset: Int = UNDEFINED_OFFSET ): IrSimpleFunction = addFunction { + this.startOffset = startOffset + this.endOffset = endOffset this.name = Name.identifier(name) this.returnType = returnType this.modality = modality diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt index 1dee4c228fd..e097fe6dcf8 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AddContinuationLowering.kt @@ -158,7 +158,7 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower val backendContext = context val invokeSuspend = context.ir.symbols.continuationImplClass.owner.functions .single { it.name == Name.identifier(INVOKE_SUSPEND_METHOD_NAME) } - addFunctionOverride(invokeSuspend) { function -> + addFunctionOverride(invokeSuspend, irFunction.startOffset, irFunction.endOffset) { function -> +irSetField(irGet(function.dispatchReceiverParameter!!), resultField, irGet(function.valueParameters[0])) // There can be three kinds of suspend function call: // 1) direct call from another suspend function/lambda diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt index 190a3c95274..044ac58d71c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SuspendLambdaLowering.kt @@ -73,17 +73,21 @@ private fun IrFunction.capturesCrossinline(): Boolean { } internal abstract class SuspendLoweringUtils(protected val context: JvmBackendContext) { - protected fun IrClass.addFunctionOverride(function: IrSimpleFunction): IrSimpleFunction = - addFunction(function.name.asString(), function.returnType).apply { + protected fun IrClass.addFunctionOverride( + function: IrSimpleFunction, startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET + ): IrSimpleFunction = + addFunction(function.name.asString(), function.returnType, startOffset = startOffset, endOffset = endOffset).apply { overriddenSymbols = listOf(function.symbol) valueParameters = function.valueParameters.map { it.copyTo(this) } } protected fun IrClass.addFunctionOverride( function: IrSimpleFunction, + startOffset: Int = UNDEFINED_OFFSET, + endOffset: Int = UNDEFINED_OFFSET, makeBody: IrBlockBodyBuilder.(IrFunction) -> Unit ): IrSimpleFunction = - addFunctionOverride(function).apply { + addFunctionOverride(function, startOffset, endOffset).apply { body = context.createIrBuilder(symbol).irBlockBody { makeBody(this@apply) } } @@ -196,7 +200,7 @@ private class SuspendLambdaLowering(context: JvmBackendContext) : SuspendLowerin it.owner.name.asString() == INVOKE_SUSPEND_METHOD_NAME && it.owner.valueParameters.size == 1 && it.owner.valueParameters[0].type.isKotlinResult() }.owner - return addFunctionOverride(superMethod).apply { + return addFunctionOverride(superMethod, irFunction.startOffset, irFunction.endOffset).apply { body = irFunction.moveBodyTo(this, mapOf())?.transform(object : IrElementTransformerVoid() { override fun visitGetValue(expression: IrGetValue): IrExpression { val parameter = (expression.symbol.owner as? IrValueParameter)?.takeIf { it.parent == irFunction } diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested.out index c2366ab8b8e..f94e16f6ad4 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested.out @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR LineBreakpoint created at sequenceNested.kt:6 Run Java Connected to the target VM diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested2.ir.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested2.ir.out new file mode 100644 index 00000000000..c20f56c36fb --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested2.ir.out @@ -0,0 +1,14 @@ +LineBreakpoint created at sequenceNested2.kt:8 +Run Java +Connected to the target VM +sequenceNested2.kt:8 +sequenceNested2.kt:9 +sequenceNested2.kt:10 +sequenceNested2.kt:11 +sequenceNested2.kt:23 +sequenceNested2.kt:23 +sequenceNested2.kt:23 +sequenceNested2.kt:24 +Disconnected from the target VM + +Process finished with exit code 0 diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested2.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested2.out index 0864d64bb1b..a0f52df12a1 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested2.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceNested2.out @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR LineBreakpoint created at sequenceNested2.kt:8 Run Java Connected to the target VM diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceSimple.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceSimple.out index 1213f2a7b4c..6c1129c922b 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceSimple.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/coroutines/sequenceSimple.out @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR LineBreakpoint created at sequenceSimple.kt:6 Run Java Connected to the target VM diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/soSuspendableCallInEndOfFun.out b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/soSuspendableCallInEndOfFun.out index 2870e26e69f..5e0cd181de2 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/soSuspendableCallInEndOfFun.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/stepping/stepOver/soSuspendableCallInEndOfFun.out @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR LineBreakpoint created at soSuspendableCallInEndOfFun.kt:29 Run Java Connected to the target VM