diff --git a/compiler/testData/codegen/box/specialBuiltins/throwableImpl.kt b/compiler/testData/codegen/box/specialBuiltins/throwableImpl.kt index 2f6aeaa6b55..ad070a0298c 100644 --- a/compiler/testData/codegen/box/specialBuiltins/throwableImpl.kt +++ b/compiler/testData/codegen/box/specialBuiltins/throwableImpl.kt @@ -17,5 +17,5 @@ fun box(): String { return "OK" } - return "fail: MyThrowable wasn't catched." + return "fail: MyThrowable wasn't caught." } diff --git a/compiler/testData/codegen/box/specialBuiltins/throwableImplWithSecondaryConstructor.kt b/compiler/testData/codegen/box/specialBuiltins/throwableImplWithSecondaryConstructor.kt new file mode 100644 index 00000000000..afa627c4598 --- /dev/null +++ b/compiler/testData/codegen/box/specialBuiltins/throwableImplWithSecondaryConstructor.kt @@ -0,0 +1,21 @@ +class MyThrowable : Throwable { + val x: String + + constructor(x: String, message: String, cause: Throwable? = null) : super(x + message, cause) { + this.x = x + } +} + +fun box(): String { + try { + throw MyThrowable("O", "K") + } + catch (t: MyThrowable) { + if (t.cause != null) return "fail t.cause" + if (t.message != "OK") return "fail t.message: ${t.message}" + if (t.x != "O") return "fail t.x: ${t.x}" + return "OK" + } + + return "fail: MyThrowable wasn't caught." +} diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 1f37b9095ec..4a6fd5e525d 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -16235,6 +16235,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("throwableImplWithSecondaryConstructor.kt") + public void testThrowableImplWithSecondaryConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImplWithSecondaryConstructor.kt"); + doTest(fileName); + } + @TestMetadata("valuesInsideEnum.kt") public void testValuesInsideEnum() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index af8500a45a5..c71fe292c37 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -16235,6 +16235,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("throwableImplWithSecondaryConstructor.kt") + public void testThrowableImplWithSecondaryConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImplWithSecondaryConstructor.kt"); + doTest(fileName); + } + @TestMetadata("valuesInsideEnum.kt") public void testValuesInsideEnum() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java index 7df8cea0b33..e07a197656e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java @@ -16235,6 +16235,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis doTest(fileName); } + @TestMetadata("throwableImplWithSecondaryConstructor.kt") + public void testThrowableImplWithSecondaryConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImplWithSecondaryConstructor.kt"); + doTest(fileName); + } + @TestMetadata("valuesInsideEnum.kt") public void testValuesInsideEnum() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.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 eddc178011b..2749ba877d5 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 @@ -20499,6 +20499,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("throwableImplWithSecondaryConstructor.kt") + public void testThrowableImplWithSecondaryConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/throwableImplWithSecondaryConstructor.kt"); + doTest(fileName); + } + @TestMetadata("valuesInsideEnum.kt") public void testValuesInsideEnum() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/specialBuiltins/valuesInsideEnum.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt index 06cbb6aa193..bd3d3a0ee82 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/ClassTranslator.kt @@ -252,13 +252,23 @@ class ClassTranslator private constructor( val delegationClassDescriptor = (resolvedCall?.resultingDescriptor as? ClassConstructorDescriptor)?.constructedClass if (resolvedCall != null && !KotlinBuiltIns.isAny(delegationClassDescriptor!!)) { - superCallGenerators += { - val delegationConstructor = resolvedCall.resultingDescriptor - val innerContext = context.innerBlock() - val statement = CallTranslator.translate(innerContext, resolvedCall) - .toInvocationWith(leadingArgs, delegationConstructor.valueParameters.size, thisNameRef).makeStmt() - it += innerContext.currentBlock.statements - it += statement + if (TranslationUtils.isImmediateSubtypeOfError(classDescriptor)) { + superCallGenerators += { + val innerContext = context().innerBlock() + ClassInitializerTranslator.emulateSuperCallToNativeError( + innerContext, classDescriptor, resolvedCall, thisNameRef.deepCopy()) + it += innerContext.currentBlock.statements + } + } + else { + superCallGenerators += { + val delegationConstructor = resolvedCall.resultingDescriptor + val innerContext = context.innerBlock() + val statement = CallTranslator.translate(innerContext, resolvedCall) + .toInvocationWith(leadingArgs, delegationConstructor.valueParameters.size, thisNameRef).makeStmt() + it += innerContext.currentBlock.statements + it += statement + } } } diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java index 3f57e42b142..45b03b7eb81 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/initializer/ClassInitializerTranslator.java @@ -189,7 +189,7 @@ public final class ClassInitializerTranslator extends AbstractTranslator { } if (TranslationUtils.isImmediateSubtypeOfError(classDescriptor)) { - emulateSuperCallToNativeError(superCall); + emulateSuperCallToNativeError(context, classDescriptor, superCall, JsLiteral.THIS); return; } @@ -257,11 +257,17 @@ public final class ClassInitializerTranslator extends AbstractTranslator { } } - private void emulateSuperCallToNativeError(@NotNull ResolvedCall superCall) { + public static void emulateSuperCallToNativeError( + @NotNull TranslationContext context, + @NotNull ClassDescriptor classDescriptor, + @NotNull ResolvedCall superCall, + @NotNull JsExpression receiver + ) { ClassDescriptor superClass = DescriptorUtilsKt.getSuperClassOrAny(classDescriptor); JsExpression superClassRef = ReferenceTranslator.translateAsTypeReference(superClass, context); - JsExpression superInvocation = new JsInvocation(Namer.getFunctionCallRef(superClassRef), JsLiteral.THIS); - initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement(superInvocation)); + JsExpression superInvocation = new JsInvocation(Namer.getFunctionCallRef(superClassRef), receiver.deepCopy()); + List statements = context.getCurrentBlock().getStatements(); + statements.add(JsAstUtils.asSyntheticStatement(superInvocation)); JsExpression messageArgument = JsLiteral.NULL; JsExpression causeArgument = JsLiteral.NULL; @@ -283,21 +289,19 @@ public final class ClassInitializerTranslator extends AbstractTranslator { causeArgument = jsValue; } else { - initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement(jsValue)); + statements.add(JsAstUtils.asSyntheticStatement(jsValue)); } } PropertyDescriptor messageProperty = DescriptorUtils.getPropertyByName( classDescriptor.getUnsubstitutedMemberScope(), Name.identifier("message")); - JsExpression messageRef = pureFqn(context.getNameForBackingField(messageProperty), JsLiteral.THIS); - initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement( - JsAstUtils.assignment(messageRef, messageArgument))); + JsExpression messageRef = pureFqn(context.getNameForBackingField(messageProperty), receiver.deepCopy()); + statements.add(JsAstUtils.asSyntheticStatement(JsAstUtils.assignment(messageRef, messageArgument))); PropertyDescriptor causeProperty = DescriptorUtils.getPropertyByName( classDescriptor.getUnsubstitutedMemberScope(), Name.identifier("cause")); - JsExpression causeRef = pureFqn(context.getNameForBackingField(causeProperty), JsLiteral.THIS); - initFunction.getBody().getStatements().add(JsAstUtils.asSyntheticStatement( - JsAstUtils.assignment(causeRef, causeArgument))); + JsExpression causeRef = pureFqn(context.getNameForBackingField(causeProperty), receiver.deepCopy()); + statements.add(JsAstUtils.asSyntheticStatement(JsAstUtils.assignment(causeRef, causeArgument))); } @NotNull