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 c23133c0062..4552cbb0682 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 @@ -245,7 +245,7 @@ abstract class ClassCodegen protected constructor( if (field.origin != JvmLoweredDeclarationOrigin.CONTINUATION_CLASS_RESULT_FIELD) { val skipNullabilityAnnotations = - flags and Opcodes.ACC_SYNTHETIC != 0 || flags and Opcodes.ACC_PRIVATE != 0 || + flags and (Opcodes.ACC_SYNTHETIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_ENUM) != 0 || field.origin == JvmLoweredDeclarationOrigin.FIELD_FOR_STATIC_LAMBDA_INSTANCE object : AnnotationCodegen(this@ClassCodegen, context, skipNullabilityAnnotations) { override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt index 1300032b14f..b3b4e9d5163 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt @@ -70,7 +70,8 @@ class FunctionCodegen( } if (irFunction.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER && - irFunction.origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR + irFunction.origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR && + irFunction.origin != IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER ) { val skipNullabilityAnnotations = flags and Opcodes.ACC_PRIVATE != 0 || flags and Opcodes.ACC_SYNTHETIC != 0 object : AnnotationCodegen(classCodegen, context, skipNullabilityAnnotations) { @@ -145,6 +146,7 @@ class FunctionCodegen( val modalityFlag = when ((this as? IrSimpleFunction)?.modality) { Modality.FINAL -> when { origin == JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER -> 0 + origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> 0 parentAsClass.isInterface && body != null -> 0 parentAsClass.isAnnotationClass && !isStatic -> Opcodes.ACC_ABSTRACT else -> Opcodes.ACC_FINAL diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index f649fa0b6df..69f52e650cc 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -576,6 +576,9 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle // There is never a problem with visibility of inline functions, as those don't end up as Java entities if (declaration is IrFunction && declaration.isInline) return true + // Enum entry constructors are generated as package-private and are accessed only from corresponding enum class + if (declaration is IrConstructor && declaration.constructedClass.isEnumEntry) return true + // `internal` maps to public and requires no accessor. if (!withSuper && !declaration.visibility.isPrivate && !declaration.visibility.isProtected) return true diff --git a/compiler/testData/codegen/bytecodeListing/enum.kt b/compiler/testData/codegen/bytecodeListing/enum.kt new file mode 100644 index 00000000000..a193aa6cfd4 --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/enum.kt @@ -0,0 +1,21 @@ +enum class SimpleEnum { + A, B, C +} + +enum class WithConstructor(val x: String) { + A("1"), B("2"), C("3") +} + +enum class WithEntryClass { + A { + override fun foo() {} + } + ; + abstract fun foo() +} + +annotation class Ann + +enum class WithAnnotations { + @Ann A, @Ann B +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeListing/enum.txt b/compiler/testData/codegen/bytecodeListing/enum.txt new file mode 100644 index 00000000000..bb8fadbfc6c --- /dev/null +++ b/compiler/testData/codegen/bytecodeListing/enum.txt @@ -0,0 +1,60 @@ +@java.lang.annotation.Retention +@kotlin.Metadata +public annotation class Ann + +@kotlin.Metadata +public final enum class SimpleEnum { + private synthetic final static field $VALUES: SimpleEnum[] + public final enum static field A: SimpleEnum + public final enum static field B: SimpleEnum + public final enum static field C: SimpleEnum + static method (): void + private method (p0: java.lang.String, p1: int): void + public static method valueOf(p0: java.lang.String): SimpleEnum + public static method values(): SimpleEnum[] +} + +@kotlin.Metadata +public final enum class WithAnnotations { + private synthetic final static field $VALUES: WithAnnotations[] + public final enum static @Ann field A: WithAnnotations + public final enum static @Ann field B: WithAnnotations + static method (): void + private method (p0: java.lang.String, p1: int): void + public static method valueOf(p0: java.lang.String): WithAnnotations + public static method values(): WithAnnotations[] +} + +@kotlin.Metadata +public final enum class WithConstructor { + private synthetic final static field $VALUES: WithConstructor[] + public final enum static field A: WithConstructor + public final enum static field B: WithConstructor + public final enum static field C: WithConstructor + private final field x: java.lang.String + static method (): void + private method (p0: java.lang.String, p1: int, p2: java.lang.String): void + public final @org.jetbrains.annotations.NotNull method getX(): java.lang.String + public static method valueOf(p0: java.lang.String): WithConstructor + public static method values(): WithConstructor[] +} + +@kotlin.Metadata +final class WithEntryClass$A { + inner class WithEntryClass$A + method (p0: java.lang.String, p1: int): void + public method foo(): void +} + +@kotlin.Metadata +public abstract enum class WithEntryClass { + private synthetic final static field $VALUES: WithEntryClass[] + public final enum static field A: WithEntryClass + inner class WithEntryClass$A + static method (): void + private method (p0: java.lang.String, p1: int): void + public synthetic method (p0: java.lang.String, p1: int, p2: kotlin.jvm.internal.DefaultConstructorMarker): void + public abstract method foo(): void + public static method valueOf(p0: java.lang.String): WithEntryClass + public static method values(): WithEntryClass[] +} diff --git a/compiler/testData/codegen/bytecodeText/inline/specialEnumFunction.kt b/compiler/testData/codegen/bytecodeText/inline/specialEnumFunction.kt index 62c928e4f47..bcbce3b8778 100644 --- a/compiler/testData/codegen/bytecodeText/inline/specialEnumFunction.kt +++ b/compiler/testData/codegen/bytecodeText/inline/specialEnumFunction.kt @@ -13,7 +13,6 @@ fun main() { value() } -// JVM_TEMPLATES //2 reifiedOperationMarker //1 INVOKESTATIC kotlin/jvm/internal/Intrinsics\.reifiedOperationMarker \(ILjava/lang/String;\)V\s*ICONST_0\s*ANEWARRAY java/lang/Enum //1 INVOKESTATIC Z\.values \(\)\[LZ; @@ -22,14 +21,3 @@ fun main() { //1 INVOKESTATIC Z\.valueOf \(Ljava/lang/String;\)LZ; //1 public static valueOf //2 INVOKESTATIC java/lang/Enum.valueOf \(Ljava/lang/Class;Ljava/lang/String;\)Ljava/lang/Enum; - -// JVM_IR_TEMPLATES -//2 reifiedOperationMarker -//1 INVOKESTATIC kotlin/jvm/internal/Intrinsics\.reifiedOperationMarker \(ILjava/lang/String;\)V\s*ICONST_0\s*ANEWARRAY java/lang/Enum -//1 INVOKESTATIC Z\.values \(\)\[LZ; -//4 valueOf -//1 INVOKESTATIC kotlin/jvm/internal/Intrinsics\.reifiedOperationMarker \(ILjava/lang/String;\)V\s*ACONST_NULL\s*ALOAD 2\s*INVOKESTATIC java/lang/Enum\.valueOf \(Ljava/lang/Class;Ljava/lang/String;\)Ljava/lang/Enum; -//1 INVOKESTATIC Z\.valueOf \(Ljava/lang/String;\)LZ; -//1 public final static valueOf -// ^ valueOf is generated as 'public final static' in JVM_IR -//2 INVOKESTATIC java/lang/Enum.valueOf \(Ljava/lang/Class;Ljava/lang/String;\)Ljava/lang/Enum; \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java index 1ae91508dd5..8081ae7c57f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeListingTestGenerated.java @@ -54,6 +54,11 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest { runTest("compiler/testData/codegen/bytecodeListing/emptyMultifileFacade.kt"); } + @TestMetadata("enum.kt") + public void testEnum() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/enum.kt"); + } + @TestMetadata("extension.kt") public void testExtension() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/extension.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java index ecb9ecbd650..06ebc42deab 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeListingTestGenerated.java @@ -54,6 +54,11 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes runTest("compiler/testData/codegen/bytecodeListing/emptyMultifileFacade.kt"); } + @TestMetadata("enum.kt") + public void testEnum() throws Exception { + runTest("compiler/testData/codegen/bytecodeListing/enum.kt"); + } + @TestMetadata("extension.kt") public void testExtension() throws Exception { runTest("compiler/testData/codegen/bytecodeListing/extension.kt");