PSI2IR fix SOE in testKt47450 (again)

This commit is contained in:
Dmitry Petrov
2022-02-03 16:16:24 +03:00
committed by Space
parent 78d80181e2
commit e111c60458
10 changed files with 40 additions and 31 deletions
@@ -140,7 +140,7 @@ fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffse
is SuperCallReceiverValue -> is SuperCallReceiverValue ->
generateThisOrSuperReceiver(receiver, receiver.thisType.constructor.declarationDescriptor as ClassDescriptor) generateThisOrSuperReceiver(receiver, receiver.thisType.constructor.declarationDescriptor as ClassDescriptor)
is ExpressionReceiver -> is ExpressionReceiver ->
generateExpression(receiver.expression) generateStatement(receiver.expression) as IrExpression
is ExtensionReceiver -> { is ExtensionReceiver -> {
IrGetValueImpl( IrGetValueImpl(
defaultStartOffset, defaultStartOffset, irReceiverType, defaultStartOffset, defaultStartOffset, irReceiverType,
@@ -306,7 +306,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
} }
} }
private fun generateFunctionCall( internal fun generateFunctionCall(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor,
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
@@ -25,7 +25,9 @@ import org.jetbrains.kotlin.ir.descriptors.IrBuiltInsOverDescriptors
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -527,15 +529,19 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
} }
} }
private fun generateBinaryOperatorAsCall(expression: KtBinaryExpression, origin: IrStatementOrigin?): IrExpression = private fun generateBinaryOperatorAsCall(expression: KtBinaryExpression, origin: IrStatementOrigin?): IrExpression {
if (isDynamicBinaryOperator(expression)) if (isDynamicBinaryOperator(expression)) {
generateDynamicBinaryExpression(expression) return generateDynamicBinaryExpression(expression)
else }
CallGenerator(statementGenerator) val callBuilder = statementGenerator.pregenerateCall(getResolvedCall(expression)!!)
.generateCall( return CallGenerator(statementGenerator).generateFunctionCall(
expression.startOffsetSkippingComments, expression.endOffset, callBuilder.descriptor as? FunctionDescriptor
statementGenerator.pregenerateCall(getResolvedCall(expression)!!), origin ?: throw AssertionError("Operator call resolved to a non-function: ${callBuilder.descriptor}"),
) expression.startOffsetSkippingComments, expression.endOffset,
origin,
callBuilder
)
}
private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, origin: IrStatementOrigin): IrExpression { private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, origin: IrStatementOrigin): IrExpression {
val resolvedCall = getResolvedCall(expression)!! val resolvedCall = getResolvedCall(expression)!!
@@ -84,11 +84,11 @@ val CallBuilder.explicitReceiverType: KotlinType?
fun CallBuilder.setExplicitReceiverValue(explicitReceiverValue: IntermediateValue) { fun CallBuilder.setExplicitReceiverValue(explicitReceiverValue: IntermediateValue) {
val previousCallReceiver = callReceiver val previousCallReceiver = callReceiver
callReceiver = object : CallReceiver { callReceiver = object : CallReceiver {
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression { override fun call(builder: CallExpressionBuilder): IrExpression {
return previousCallReceiver.call { dispatchReceiverValue, _, contextReceiverValues -> return previousCallReceiver.call { dispatchReceiverValue, _, contextReceiverValues ->
val newDispatchReceiverValue = if (hasExtensionReceiver) dispatchReceiverValue else explicitReceiverValue val newDispatchReceiverValue = if (hasExtensionReceiver) dispatchReceiverValue else explicitReceiverValue
val newExtensionReceiverValue = if (hasExtensionReceiver) explicitReceiverValue else null val newExtensionReceiverValue = if (hasExtensionReceiver) explicitReceiverValue else null
withDispatchAndExtensionAndContextReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues) builder.withReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues)
} }
} }
} }
@@ -23,8 +23,7 @@ class ExtensionInvokeCallReceiver(
private val functionReceiver: IntermediateValue, private val functionReceiver: IntermediateValue,
private val extensionInvokeReceiver: IntermediateValue private val extensionInvokeReceiver: IntermediateValue
) : CallReceiver { ) : CallReceiver {
override fun call(builder: CallExpressionBuilder): IrExpression {
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
// extensionInvokeReceiver is actually a first argument: // extensionInvokeReceiver is actually a first argument:
// receiver.extFun(p1, ..., pN) // receiver.extFun(p1, ..., pN)
// => // =>
@@ -34,6 +33,6 @@ class ExtensionInvokeCallReceiver(
"Extension 'invoke' call should have null as its 1st value argument, got: ${callBuilder.irValueArgumentsByIndex[0]}" "Extension 'invoke' call should have null as its 1st value argument, got: ${callBuilder.irValueArgumentsByIndex[0]}"
} }
callBuilder.irValueArgumentsByIndex[0] = extensionInvokeReceiver.load() callBuilder.irValueArgumentsByIndex[0] = extensionInvokeReceiver.load()
return withDispatchAndExtensionAndContextReceivers(functionReceiver, null, emptyList()) return builder.withReceivers(functionReceiver, null, emptyList())
} }
} }
@@ -27,7 +27,7 @@ fun IrVariable.loadAt(startOffset: Int, endOffset: Int): IrExpression =
fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver = fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver =
object : CallReceiver { object : CallReceiver {
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression = override fun call(builder: CallExpressionBuilder): IrExpression =
this@adjustForCallee.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues -> this@adjustForCallee.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues ->
val numReceiversPresent = listOfNotNull(dispatchReceiverValue, extensionReceiverValue).size val numReceiversPresent = listOfNotNull(dispatchReceiverValue, extensionReceiverValue).size
val numReceiversExpected = listOfNotNull(callee.dispatchReceiverParameter, callee.extensionReceiverParameter).size val numReceiversExpected = listOfNotNull(callee.dispatchReceiverParameter, callee.extensionReceiverParameter).size
@@ -46,7 +46,7 @@ fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver
dispatchReceiverValue != null && callee.dispatchReceiverParameter == null -> dispatchReceiverValue dispatchReceiverValue != null && callee.dispatchReceiverParameter == null -> dispatchReceiverValue
else -> extensionReceiverValue else -> extensionReceiverValue
} }
withDispatchAndExtensionAndContextReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues) builder.withReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues)
} }
} }
@@ -35,8 +35,7 @@ class SafeCallReceiver(
val dispatchReceiver: IntermediateValue?, val dispatchReceiver: IntermediateValue?,
val isStatement: Boolean val isStatement: Boolean
) : CallReceiver { ) : CallReceiver {
override fun call(builder: CallExpressionBuilder): IrExpression {
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
val irTmp = generator.scope.createTemporaryVariable(extensionReceiver?.load() ?: dispatchReceiver!!.load(), "safe_receiver") val irTmp = generator.scope.createTemporaryVariable(extensionReceiver?.load() ?: dispatchReceiver!!.load(), "safe_receiver")
val safeReceiverValue = VariableLValue(generator.context, irTmp) val safeReceiverValue = VariableLValue(generator.context, irTmp)
@@ -50,7 +49,7 @@ class SafeCallReceiver(
extensionReceiverValue = null extensionReceiverValue = null
} }
val irResult = withDispatchAndExtensionAndContextReceivers(dispatchReceiverValue, extensionReceiverValue, contextReceivers) val irResult = builder.withReceivers(dispatchReceiverValue, extensionReceiverValue, contextReceivers)
val resultType = if (isStatement) generator.context.irBuiltIns.unitType else irResult.type.makeNullable() val resultType = if (isStatement) generator.context.irBuiltIns.unitType else irResult.type.makeNullable()
@@ -32,8 +32,7 @@ class SafeExtensionInvokeCallReceiver(
val functionReceiver: IntermediateValue, val functionReceiver: IntermediateValue,
val extensionInvokeReceiver: IntermediateValue val extensionInvokeReceiver: IntermediateValue
) : CallReceiver { ) : CallReceiver {
override fun call(builder: CallExpressionBuilder): IrExpression {
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
// extensionInvokeReceiver is actually a first argument: // extensionInvokeReceiver is actually a first argument:
// receiver?.extFun(p1, ..., pN) // receiver?.extFun(p1, ..., pN)
// => // =>
@@ -49,7 +48,7 @@ class SafeExtensionInvokeCallReceiver(
"Safe extension 'invoke' call should have null as its 1st value argument, got: ${callBuilder.irValueArgumentsByIndex[0]}" "Safe extension 'invoke' call should have null as its 1st value argument, got: ${callBuilder.irValueArgumentsByIndex[0]}"
} }
callBuilder.irValueArgumentsByIndex[0] = safeReceiverValue.load() callBuilder.irValueArgumentsByIndex[0] = safeReceiverValue.load()
val irResult = withDispatchAndExtensionAndContextReceivers(functionReceiver, null, emptyList()) val irResult = builder.withReceivers(functionReceiver, null, emptyList())
val resultType = irResult.type.makeNullable() val resultType = irResult.type.makeNullable()
@@ -23,8 +23,7 @@ class SimpleCallReceiver(
private val extensionReceiverValue: IntermediateValue?, private val extensionReceiverValue: IntermediateValue?,
private val contextReceiverValues: List<IntermediateValue> private val contextReceiverValues: List<IntermediateValue>
) : CallReceiver { ) : CallReceiver {
override fun call(builder: CallExpressionBuilder): IrExpression {
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression { return builder.withReceivers(dispatchReceiverValue, extensionReceiverValue, contextReceiverValues)
return withDispatchAndExtensionAndContextReceivers(dispatchReceiverValue, extensionReceiverValue, contextReceiverValues)
} }
} }
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.types.KotlinType
interface IntermediateValue { interface IntermediateValue {
fun load(): IrExpression fun load(): IrExpression
@@ -35,6 +34,14 @@ interface AssignmentReceiver {
fun assign(value: IrExpression): IrExpression = assign { it.store(value) } fun assign(value: IrExpression): IrExpression = assign { it.store(value) }
} }
interface CallReceiver { fun interface CallExpressionBuilder {
fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression fun withReceivers(
dispatchReceiver: IntermediateValue?,
extensionReceiver: IntermediateValue?,
contextReceivers: List<IntermediateValue>
): IrExpression
}
interface CallReceiver {
fun call(builder: CallExpressionBuilder): IrExpression
} }