From 0aee2d0568fd9befb331ac4c22207c2431795aed Mon Sep 17 00:00:00 2001 From: Ting-Yuan Huang Date: Mon, 20 May 2019 17:52:01 -0700 Subject: [PATCH] Fix signature generation for calls to enum and inner class constructors The synthesized arguments caused the size of default value mask off by one when it is close to the boundary of Int.SIZE, which in turn resulted in wrong signature at call sites. --- .../kotlin/codegen/state/KotlinTypeMapper.kt | 15 ++++-- .../backend/jvm/codegen/ExpressionCodegen.kt | 2 +- .../constructor/innerClass32Args.kt | 52 +++++++++++++++++++ .../codegen/box/enum/manyDefaultParameters.kt | 1 - .../codegen/BlackBoxCodegenTestGenerated.java | 5 ++ .../LightAnalysisModeTestGenerated.java | 5 ++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 ++ .../IrJsCodegenBoxTestGenerated.java | 5 ++ .../semantics/JsCodegenBoxTestGenerated.java | 5 ++ 9 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/codegen/box/defaultArguments/constructor/innerClass32Args.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt index cb16fc4d397..29409026b0b 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt @@ -912,7 +912,15 @@ class KotlinTypeMapper @JvmOverloads constructor( jvmSignature, if (isStaticMethod(kind, functionDescriptor) || isStaticDeclaration(functionDescriptor) || isConstructor) null else ownerType.descriptor, - functionDescriptor.unwrapFrontendVersion() + functionDescriptor.unwrapFrontendVersion(), + if (isIrBackend && isConstructor) { + val containingDeclaration = functionDescriptor.containingDeclaration + when { + isEnumClass(containingDeclaration) -> 2 + (containingDeclaration as? ClassDescriptor)?.isInner == true -> 1 + else -> 0 + } + } else 0 ) return Method(if (isConstructor) "" else jvmSignature.name + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor) @@ -1578,10 +1586,11 @@ class KotlinTypeMapper @JvmOverloads constructor( private fun getDefaultDescriptor( method: Method, dispatchReceiverDescriptor: String?, - callableDescriptor: CallableDescriptor + callableDescriptor: CallableDescriptor, + extraArgsShift: Int ): String { val descriptor = method.descriptor - val maskArgumentsCount = (callableDescriptor.valueParameters.size + Integer.SIZE - 1) / Integer.SIZE + val maskArgumentsCount = (callableDescriptor.valueParameters.size - extraArgsShift + Integer.SIZE - 1) / Integer.SIZE val defaultConstructorMarkerType = if (isConstructor(method) || isInlineClassConstructor(callableDescriptor)) DEFAULT_CONSTRUCTOR_MARKER else diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index f054fb46e25..0773de2e0f7 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -327,13 +327,13 @@ class ExpressionCodegen( } callGenerator.beforeValueParametersStart() - val defaultMask = DefaultCallArgs(callable.valueParameterTypes.size) val extraArgsShift = when { callee is IrConstructor && callee.parentAsClass.isEnumClass -> 2 callee is IrConstructor && callee.parentAsClass.isInner -> 1 // skip the `$outer` parameter else -> 0 } + val defaultMask = DefaultCallArgs(callable.valueParameterTypes.size - extraArgsShift) val typeParameters = if (callee is IrConstructor) callee.parentAsClass.typeParameters + callee.typeParameters else diff --git a/compiler/testData/codegen/box/defaultArguments/constructor/innerClass32Args.kt b/compiler/testData/codegen/box/defaultArguments/constructor/innerClass32Args.kt new file mode 100644 index 00000000000..ae3fc3ab71e --- /dev/null +++ b/compiler/testData/codegen/box/defaultArguments/constructor/innerClass32Args.kt @@ -0,0 +1,52 @@ +class A { + inner class B(val a: Int = 1, + val b: Int = 2, + val c: Int = 3, + val d: Int = 4, + val e: Int = 5, + val f: Int = 6, + val g: Int = 7, + val h: Int = 8, + val i: Int = 9, + val j: Int = 10, + val k: Int = 11, + val l: Int = 12, + val m: Int = 13, + val n: Int = 14, + val o: Int = 15, + val p: Int = 16, + val q: Int = 17, + val r: Int = 18, + val s: Int = 19, + val t: Int = 20, + val u: Int = 21, + val v: Int = 22, + val w: Int = 23, + val x: Int = 24, + val y: Int = 25, + val z: Int = 26, + val aa: Int = 27, + val bb: Int = 28, + val cc: Int = 29, + val dd: Int = 30, + val ee: Int = 31, + val ff: Int = 32) { + override fun toString(): String { + return "$a $b $c $d $e $f $g $h $i $j $k $l $m $n $o $p $q $r $s $t $u $v $w $x $y $z $aa $bb $cc $dd $ee $ff" + } + } +} + +fun box(): String { + val test1 = A().B().toString() + if (test1 != "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32") { + return "test1 = $test1" + } + + val test2 = A().B(4, e = 8, f = 15, w = 16, aa = 23, ff = 42).toString() + if (test2 != "4 2 3 4 8 15 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 16 24 25 26 23 28 29 30 31 42") { + return "test2 = $test2" + } + + return "OK" +} diff --git a/compiler/testData/codegen/box/enum/manyDefaultParameters.kt b/compiler/testData/codegen/box/enum/manyDefaultParameters.kt index 96d859b71c6..a094da96f27 100644 --- a/compiler/testData/codegen/box/enum/manyDefaultParameters.kt +++ b/compiler/testData/codegen/box/enum/manyDefaultParameters.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR enum class ClassTemplate( // var bug: Int = 1, var code: Int, diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index a688bb7c0e8..33e573996f9 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -8937,6 +8937,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/defaultArguments/constructor/enumWithTwoDoubleDefArgs.kt"); } + @TestMetadata("innerClass32Args.kt") + public void testInnerClass32Args() throws Exception { + runTest("compiler/testData/codegen/box/defaultArguments/constructor/innerClass32Args.kt"); + } + @TestMetadata("kt2852.kt") public void testKt2852() throws Exception { runTest("compiler/testData/codegen/box/defaultArguments/constructor/kt2852.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index fc7179dce12..be86f112d5d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -8937,6 +8937,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/defaultArguments/constructor/enumWithTwoDoubleDefArgs.kt"); } + @TestMetadata("innerClass32Args.kt") + public void testInnerClass32Args() throws Exception { + runTest("compiler/testData/codegen/box/defaultArguments/constructor/innerClass32Args.kt"); + } + @TestMetadata("kt2852.kt") public void testKt2852() throws Exception { runTest("compiler/testData/codegen/box/defaultArguments/constructor/kt2852.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 3e100eab53a..aa0a6ba80a3 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -8937,6 +8937,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/defaultArguments/constructor/enumWithTwoDoubleDefArgs.kt"); } + @TestMetadata("innerClass32Args.kt") + public void testInnerClass32Args() throws Exception { + runTest("compiler/testData/codegen/box/defaultArguments/constructor/innerClass32Args.kt"); + } + @TestMetadata("kt2852.kt") public void testKt2852() throws Exception { runTest("compiler/testData/codegen/box/defaultArguments/constructor/kt2852.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 6a6d79f1a1d..b37ff725df1 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -6742,6 +6742,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/defaultArguments/constructor/enumWithTwoDoubleDefArgs.kt"); } + @TestMetadata("innerClass32Args.kt") + public void testInnerClass32Args() throws Exception { + runTest("compiler/testData/codegen/box/defaultArguments/constructor/innerClass32Args.kt"); + } + @TestMetadata("kt2852.kt") public void testKt2852() throws Exception { runTest("compiler/testData/codegen/box/defaultArguments/constructor/kt2852.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 8538745a1c2..5cce8aa90ac 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -7827,6 +7827,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/defaultArguments/constructor/enumWithTwoDoubleDefArgs.kt"); } + @TestMetadata("innerClass32Args.kt") + public void testInnerClass32Args() throws Exception { + runTest("compiler/testData/codegen/box/defaultArguments/constructor/innerClass32Args.kt"); + } + @TestMetadata("kt2852.kt") public void testKt2852() throws Exception { runTest("compiler/testData/codegen/box/defaultArguments/constructor/kt2852.kt");