PSI2IR fix SOE in testKt47450 (again)
This commit is contained in:
+1
-1
@@ -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,
|
||||||
|
|||||||
+16
-10
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -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()
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -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()
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user