'!!' 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.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisClassReceiver
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import java.lang.AssertionError
|
||||
|
||||
@@ -60,6 +61,7 @@ class OperatorExpressionGenerator(
|
||||
return when (irOperator) {
|
||||
null -> throw AssertionError("Unexpected postfix operator: $ktOperator")
|
||||
in INCREMENT_DECREMENT_OPERATORS -> generatePostfixIncrementDecrementOperator(expression, irOperator)
|
||||
IrOperator.EXCLEXCL -> generateExclExclOperator(expression, irOperator)
|
||||
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 {
|
||||
val resolvedCall = getResolvedCall(expression)!!
|
||||
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,
|
||||
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
|
||||
fun GeneratorContext.oror(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrWhen =
|
||||
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);
|
||||
}
|
||||
|
||||
@TestMetadata("bangbang.kt")
|
||||
public void testBangbang() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/bangbang.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("booleanOperators.kt")
|
||||
public void testBooleanOperators() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/booleanOperators.kt");
|
||||
|
||||
Reference in New Issue
Block a user