From b61389f6f9dc3abc0594495740198feb0048e8e9 Mon Sep 17 00:00:00 2001 From: Mads Ager Date: Thu, 30 Sep 2021 13:11:31 +0200 Subject: [PATCH] [JVM IR] Do not generate clinit as enclosing method. The JVM and newer Android runtimes treats that the same as if there is no enclosing method. However, older Android runtimes for Android 5 and 6 throw exceptions on reflective access and even older runtimes have different behavior. To avoid those issues, exclude from enclosing method attributes. ^ KT-48754 Fixed --- .../codegen/FirBytecodeTextTestGenerated.java | 16 ++++++++++++++++ .../kotlin/backend/jvm/codegen/ClassCodegen.kt | 2 +- .../delegatedPropertiesInCompanionObject_ir.txt | 2 +- ...ileClassWithPrivateDeclarationsOnly_after.txt | 2 +- ...leClassWithPrivateDeclarationsOnly_before.txt | 2 +- .../noReceiverInCallableReferenceClasses_ir.txt | 8 ++++---- .../bytecodeText/outerClass/classInClinit.kt | 7 +++++++ .../codegen/BytecodeTextTestGenerated.java | 16 ++++++++++++++++ .../codegen/IrBytecodeTextTestGenerated.java | 16 ++++++++++++++++ 9 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 compiler/testData/codegen/bytecodeText/outerClass/classInClinit.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java index 454d62ef42d..cf47756f51f 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java @@ -4857,6 +4857,22 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest { } } + @Nested + @TestMetadata("compiler/testData/codegen/bytecodeText/outerClass") + @TestDataPath("$PROJECT_ROOT") + public class OuterClass { + @Test + public void testAllFilesPresentInOuterClass() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/outerClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("classInClinit.kt") + public void testClassInClinit() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/outerClass/classInClinit.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/bytecodeText/parameterlessMain") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 22114bab5d0..77abd551a56 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -446,7 +446,7 @@ class ClassCodegen private constructor( ?: error("Class in a non-static initializer found, but container has no constructors: ${containerClass.render()}") } else parentFunction if (enclosingFunction != null || irClass.isAnonymousInnerClass) { - val method = enclosingFunction?.let(context.methodSignatureMapper::mapAsmMethod) + val method = enclosingFunction?.let(context.methodSignatureMapper::mapAsmMethod)?.takeIf { it.name != "" } visitor.visitOuterClass(parentClassCodegen!!.type.internalName, method?.name, method?.descriptor) } } diff --git a/compiler/testData/codegen/bytecodeListing/delegatedProperty/delegatedPropertiesInCompanionObject_ir.txt b/compiler/testData/codegen/bytecodeListing/delegatedProperty/delegatedPropertiesInCompanionObject_ir.txt index c9df7343630..d1319356f16 100644 --- a/compiler/testData/codegen/bytecodeListing/delegatedProperty/delegatedPropertiesInCompanionObject_ir.txt +++ b/compiler/testData/codegen/bytecodeListing/delegatedProperty/delegatedPropertiesInCompanionObject_ir.txt @@ -43,7 +43,7 @@ public final class H1 { @kotlin.Metadata final class H2$Companion$property$2 { // source: 'delegatedPropertiesInCompanionObject.kt' - enclosing method H2.()V + enclosing class H2 public final static field INSTANCE: H2$Companion$property$2 inner (anonymous) class H2$Companion$property$2 static method (): void diff --git a/compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_after.txt b/compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_after.txt index 5265d3b0fbe..6ef698e8e11 100644 --- a/compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_after.txt +++ b/compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_after.txt @@ -1,7 +1,7 @@ @kotlin.Metadata final class FileClassWithPrivateDeclarationsOnly_afterKt$b$2 { // source: 'fileClassWithPrivateDeclarationsOnly_after.kt' - enclosing method FileClassWithPrivateDeclarationsOnly_afterKt.()V + enclosing class FileClassWithPrivateDeclarationsOnly_afterKt public final static field INSTANCE: FileClassWithPrivateDeclarationsOnly_afterKt$b$2 inner (anonymous) class FileClassWithPrivateDeclarationsOnly_afterKt$b$2 static method (): void diff --git a/compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_before.txt b/compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_before.txt index 8e85499a697..77dad020b72 100644 --- a/compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_before.txt +++ b/compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_before.txt @@ -1,7 +1,7 @@ @kotlin.Metadata final class FileClassWithPrivateDeclarationsOnly_beforeKt$b$2 { // source: 'fileClassWithPrivateDeclarationsOnly_before.kt' - enclosing method FileClassWithPrivateDeclarationsOnly_beforeKt.()V + enclosing class FileClassWithPrivateDeclarationsOnly_beforeKt public final static field INSTANCE: FileClassWithPrivateDeclarationsOnly_beforeKt$b$2 inner (anonymous) class FileClassWithPrivateDeclarationsOnly_beforeKt$b$2 static method (): void diff --git a/compiler/testData/codegen/bytecodeListing/noReceiverInCallableReferenceClasses_ir.txt b/compiler/testData/codegen/bytecodeListing/noReceiverInCallableReferenceClasses_ir.txt index e864fee3345..c887733af1d 100644 --- a/compiler/testData/codegen/bytecodeListing/noReceiverInCallableReferenceClasses_ir.txt +++ b/compiler/testData/codegen/bytecodeListing/noReceiverInCallableReferenceClasses_ir.txt @@ -10,7 +10,7 @@ public final class A { @kotlin.Metadata synthetic final class NoReceiverInCallableReferenceClassesKt$A_bar$1 { // source: 'noReceiverInCallableReferenceClasses.kt' - enclosing method NoReceiverInCallableReferenceClassesKt.()V + enclosing class NoReceiverInCallableReferenceClassesKt public final static field INSTANCE: NoReceiverInCallableReferenceClassesKt$A_bar$1 inner (anonymous) class NoReceiverInCallableReferenceClassesKt$A_bar$1 static method (): void @@ -21,7 +21,7 @@ synthetic final class NoReceiverInCallableReferenceClassesKt$A_bar$1 { @kotlin.Metadata synthetic final class NoReceiverInCallableReferenceClassesKt$A_foo$1 { // source: 'noReceiverInCallableReferenceClasses.kt' - enclosing method NoReceiverInCallableReferenceClassesKt.()V + enclosing class NoReceiverInCallableReferenceClassesKt public final static field INSTANCE: NoReceiverInCallableReferenceClassesKt$A_foo$1 inner (anonymous) class NoReceiverInCallableReferenceClassesKt$A_foo$1 static method (): void @@ -33,7 +33,7 @@ synthetic final class NoReceiverInCallableReferenceClassesKt$A_foo$1 { @kotlin.Metadata synthetic final class NoReceiverInCallableReferenceClassesKt$aBar$1 { // source: 'noReceiverInCallableReferenceClasses.kt' - enclosing method NoReceiverInCallableReferenceClassesKt.()V + enclosing class NoReceiverInCallableReferenceClassesKt inner (anonymous) class NoReceiverInCallableReferenceClassesKt$aBar$1 method (p0: java.lang.Object): void public @org.jetbrains.annotations.Nullable method get(): java.lang.Object @@ -42,7 +42,7 @@ synthetic final class NoReceiverInCallableReferenceClassesKt$aBar$1 { @kotlin.Metadata synthetic final class NoReceiverInCallableReferenceClassesKt$aFoo$1 { // source: 'noReceiverInCallableReferenceClasses.kt' - enclosing method NoReceiverInCallableReferenceClassesKt.()V + enclosing class NoReceiverInCallableReferenceClassesKt inner (anonymous) class NoReceiverInCallableReferenceClassesKt$aFoo$1 method (p0: java.lang.Object): void public synthetic bridge method invoke(): java.lang.Object diff --git a/compiler/testData/codegen/bytecodeText/outerClass/classInClinit.kt b/compiler/testData/codegen/bytecodeText/outerClass/classInClinit.kt new file mode 100644 index 00000000000..e8850d6b509 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/outerClass/classInClinit.kt @@ -0,0 +1,7 @@ +// FILE: test.kt + +// This should *not* have enclosing method . See https://youtrack.jetbrains.com/issue/KT-48754. +val a = {} + +// @TestKt$a$1.class: +// 1 OUTERCLASS TestKt null diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java index 6dd6c4eb4a9..e9f8690ae0b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java @@ -4713,6 +4713,22 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { } } + @Nested + @TestMetadata("compiler/testData/codegen/bytecodeText/outerClass") + @TestDataPath("$PROJECT_ROOT") + public class OuterClass { + @Test + public void testAllFilesPresentInOuterClass() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/outerClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + + @Test + @TestMetadata("classInClinit.kt") + public void testClassInClinit() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/outerClass/classInClinit.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/bytecodeText/parameterlessMain") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java index c8acaaa4ceb..7de1643c19f 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java @@ -4857,6 +4857,22 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { } } + @Nested + @TestMetadata("compiler/testData/codegen/bytecodeText/outerClass") + @TestDataPath("$PROJECT_ROOT") + public class OuterClass { + @Test + public void testAllFilesPresentInOuterClass() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/outerClass"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("classInClinit.kt") + public void testClassInClinit() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/outerClass/classInClinit.kt"); + } + } + @Nested @TestMetadata("compiler/testData/codegen/bytecodeText/parameterlessMain") @TestDataPath("$PROJECT_ROOT")