'!!' operator
This commit is contained in:
committed by
Dmitry Petrov
parent
92a7ecfac7
commit
57c1b3e0e2
+24
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import java.lang.AssertionError
|
import java.lang.AssertionError
|
||||||
|
|
||||||
@@ -60,6 +61,7 @@ class OperatorExpressionGenerator(
|
|||||||
return when (irOperator) {
|
return when (irOperator) {
|
||||||
null -> throw AssertionError("Unexpected postfix operator: $ktOperator")
|
null -> throw AssertionError("Unexpected postfix operator: $ktOperator")
|
||||||
in INCREMENT_DECREMENT_OPERATORS -> generatePostfixIncrementDecrementOperator(expression, irOperator)
|
in INCREMENT_DECREMENT_OPERATORS -> generatePostfixIncrementDecrementOperator(expression, irOperator)
|
||||||
|
IrOperator.EXCLEXCL -> generateExclExclOperator(expression, irOperator)
|
||||||
else -> createDummyExpression(expression, ktOperator.toString())
|
else -> createDummyExpression(expression, ktOperator.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,6 +274,28 @@ class OperatorExpressionGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun generateExclExclOperator(expression: KtPostfixExpression, irOperator: IrOperator): IrExpression {
|
||||||
|
val ktArgument = expression.baseExpression!!
|
||||||
|
val irArgument = statementGenerator.generateExpression(ktArgument)
|
||||||
|
val ktOperator = expression.operationReference
|
||||||
|
|
||||||
|
val resultType = irArgument.type.makeNotNullable()
|
||||||
|
val irBlock = IrBlockImpl(ktOperator.startOffset, ktOperator.endOffset, resultType, irOperator)
|
||||||
|
val argumentValue = createRematerializableOrTemporary(scope, irArgument, irBlock, "notnull")
|
||||||
|
val irIfThenElse = IrIfThenElseImpl(ktOperator.startOffset, ktOperator.endOffset, resultType,
|
||||||
|
context.equalsNull(ktOperator.startOffset, ktOperator.endOffset, argumentValue.load()),
|
||||||
|
context.throwNpe(ktOperator.startOffset, ktOperator.endOffset, irOperator),
|
||||||
|
argumentValue.load())
|
||||||
|
|
||||||
|
return if (irBlock.statements.isEmpty()) {
|
||||||
|
irIfThenElse
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
irBlock.addStatement(irIfThenElse)
|
||||||
|
irBlock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression {
|
private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression {
|
||||||
val resolvedCall = getResolvedCall(expression)!!
|
val resolvedCall = getResolvedCall(expression)!!
|
||||||
return CallGenerator(statementGenerator).generateCall(expression, statementGenerator.pregenerateCall(resolvedCall), irOperator)
|
return CallGenerator(statementGenerator).generateCall(expression, statementGenerator.pregenerateCall(resolvedCall), irOperator)
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ fun GeneratorContext.equalsNull(startOffset: Int, endOffset: Int, argument: IrEx
|
|||||||
primitiveOp2(startOffset, endOffset, irBuiltIns.eqeq, IrOperator.EQEQ,
|
primitiveOp2(startOffset, endOffset, irBuiltIns.eqeq, IrOperator.EQEQ,
|
||||||
argument, constNull(startOffset, endOffset))
|
argument, constNull(startOffset, endOffset))
|
||||||
|
|
||||||
|
fun GeneratorContext.throwNpe(startOffset: Int, endOffset: Int, operator: IrOperator): IrExpression =
|
||||||
|
IrNullaryPrimitiveImpl(startOffset, endOffset, operator, irBuiltIns.throwNpe)
|
||||||
|
|
||||||
// a || b == if (a) true else b
|
// a || b == if (a) true else b
|
||||||
fun GeneratorContext.oror(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrWhen =
|
fun GeneratorContext.oror(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrWhen =
|
||||||
IrIfThenElseImpl(startOffset, endOffset, builtIns.booleanType,
|
IrIfThenElseImpl(startOffset, endOffset, builtIns.booleanType,
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fun test1(a: Any?) = a!!
|
||||||
|
|
||||||
|
fun test2(a: Any?) = a?.hashCode()!!
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
FILE /bangbang.kt
|
||||||
|
FUN public fun test1(/*0*/ a: kotlin.Any?): kotlin.Any
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from=test1
|
||||||
|
WHEN type=kotlin.Any operator=null
|
||||||
|
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||||
|
arg0: GET_VAR a type=kotlin.Any? operator=null
|
||||||
|
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||||
|
then: CALL .THROW_NPE type=kotlin.Nothing operator=EXCLEXCL
|
||||||
|
else: GET_VAR a type=kotlin.Any? operator=null
|
||||||
|
FUN public fun test2(/*0*/ a: kotlin.Any?): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from=test2
|
||||||
|
BLOCK type=kotlin.Int operator=EXCLEXCL
|
||||||
|
VAR val tmp1_notnull: kotlin.Int?
|
||||||
|
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||||
|
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||||
|
arg0: GET_VAR a type=kotlin.Any? operator=null
|
||||||
|
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||||
|
then: CONST Null type=kotlin.Nothing? value='null'
|
||||||
|
else: CALL .hashCode type=kotlin.Int operator=null
|
||||||
|
$this: GET_VAR a type=kotlin.Any? operator=null
|
||||||
|
WHEN type=kotlin.Int operator=null
|
||||||
|
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||||
|
arg0: GET_VAR tmp1_notnull type=kotlin.Int? operator=null
|
||||||
|
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||||
|
then: CALL .THROW_NPE type=kotlin.Nothing operator=EXCLEXCL
|
||||||
|
else: GET_VAR tmp1_notnull type=kotlin.Int? operator=null
|
||||||
@@ -112,6 +112,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bangbang.kt")
|
||||||
|
public void testBangbang() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/bangbang.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("booleanOperators.kt")
|
@TestMetadata("booleanOperators.kt")
|
||||||
public void testBooleanOperators() throws Exception {
|
public void testBooleanOperators() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/booleanOperators.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/booleanOperators.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user