[IR] Fix modality in expect-actual checker for enum classes and enum entries

^KT-68734 Fixed
Review: https://jetbrains.team/p/kt/reviews/16319/timeline
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java
index 2415708..3b36a3e 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java
@@ -25272,6 +25272,12 @@
     @TestDataPath("$PROJECT_ROOT")
     public class Multiplatform {
       @Test
+      @TestMetadata("abstractEnumInIr.kt")
+      public void testAbstractEnumInIr() {
+        runTest("compiler/testData/diagnostics/tests/multiplatform/abstractEnumInIr.kt");
+      }
+
+      @Test
       @TestMetadata("actualClassDelegationWithImplicitType.kt")
       public void testActualClassDelegationWithImplicitType() {
         runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassDelegationWithImplicitType.kt");
diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java
index aef2bd9..7c36363 100644
--- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java
+++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java
@@ -25272,6 +25272,12 @@
     @TestDataPath("$PROJECT_ROOT")
     public class Multiplatform {
       @Test
+      @TestMetadata("abstractEnumInIr.kt")
+      public void testAbstractEnumInIr() {
+        runTest("compiler/testData/diagnostics/tests/multiplatform/abstractEnumInIr.kt");
+      }
+
+      @Test
       @TestMetadata("actualClassDelegationWithImplicitType.kt")
       public void testActualClassDelegationWithImplicitType() {
         runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassDelegationWithImplicitType.kt");
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java
index 1a9562d..6892b07 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java
@@ -21,6 +21,12 @@
 @TestDataPath("$PROJECT_ROOT")
 public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends AbstractFirLightTreeWithActualizerDiagnosticsTest {
   @Test
+  @TestMetadata("abstractEnumInIr.kt")
+  public void testAbstractEnumInIr() {
+    runTest("compiler/testData/diagnostics/tests/multiplatform/abstractEnumInIr.kt");
+  }
+
+  @Test
   @TestMetadata("actualClassDelegationWithImplicitType.kt")
   public void testActualClassDelegationWithImplicitType() {
     runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassDelegationWithImplicitType.kt");
diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java
index 1977788..b1288ccb 100644
--- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java
+++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java
@@ -21,6 +21,12 @@
 @TestDataPath("$PROJECT_ROOT")
 public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFirPsiWithActualizerDiagnosticsTest {
   @Test
+  @TestMetadata("abstractEnumInIr.kt")
+  public void testAbstractEnumInIr() {
+    runTest("compiler/testData/diagnostics/tests/multiplatform/abstractEnumInIr.kt");
+  }
+
+  @Test
   @TestMetadata("actualClassDelegationWithImplicitType.kt")
   public void testActualClassDelegationWithImplicitType() {
     runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassDelegationWithImplicitType.kt");
diff --git a/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt b/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt
index 3604053..4327343 100644
--- a/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt
+++ b/compiler/ir/ir.actualization/src/main/kotlin/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt
@@ -138,11 +138,18 @@
     override val ClassLikeSymbolMarker.modality: Modality
         get() = processIr(
             onClass = {
-                // For some reason kotlin annotations in IR have open modality and java annotations have final modality
-                // But since it's legal to actualize kotlin annotation class with java annotation class
-                //  and effectively all annotation classes have the same modality, it's ok to always return one
-                //  modality for all annotation classes (doesn't matter final or open)
-                if (it.isAnnotationClass) Modality.OPEN else it.modality
+                when {
+                    // Modality for enum classes is not trivial in IR.
+                    // That's why we need to "normalize" modality for the expect-actual checker
+                    // See FirRegularClass.enumClassModality & 940567b8bd72f69b3eb7d54ff780f98a17e6b9fc
+                    it.isEnumClass -> Modality.FINAL
+                    // For some reason kotlin annotations in IR have open modality and java annotations have final modality
+                    // But since it's legal to actualize kotlin annotation class with java annotation class
+                    //  and effectively all annotation classes have the same modality, it's ok to always return one
+                    //  modality for all annotation classes (doesn't matter final or open)
+                    it.isAnnotationClass -> Modality.OPEN
+                    else -> it.modality
+                }
             },
             onTypeAlias = { Modality.FINAL }
         )
@@ -151,7 +158,8 @@
 
     override val CallableSymbolMarker.modality: Modality?
         get() = when (this) {
-            is IrConstructorSymbol -> Modality.FINAL
+            // owner.modality is null for IrEnumEntrySymbol
+            is IrEnumEntrySymbol, is IrConstructorSymbol -> Modality.FINAL
             is IrSymbol -> (owner as? IrOverridableMember)?.modality
             else -> shouldNotBeCalled()
         }
diff --git a/compiler/testData/diagnostics/tests/multiplatform/abstractEnumInIr.kt b/compiler/testData/diagnostics/tests/multiplatform/abstractEnumInIr.kt
new file mode 100644
index 0000000..b1f7827
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/multiplatform/abstractEnumInIr.kt
@@ -0,0 +1,21 @@
+// FIR_IDENTICAL
+// MODULE: m1-common
+// FILE: common.kt
+// ISSUE: KT-68734
+expect enum class MMKVMode {
+    SINGLE_PROCESS,
+    MULTI_PROCESS,
+}
+
+// MODULE: m1-jvm()()(m1-common)
+// FILE: jvm.kt
+actual enum class MMKVMode {
+    SINGLE_PROCESS {
+        override val rawValue: String = "single"
+    },
+    MULTI_PROCESS {
+        override val rawValue: String = "multi"
+    };
+
+    abstract val rawValue: String
+}
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
index b7ada4c..68a701a 100644
--- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
+++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java
@@ -25272,6 +25272,12 @@
     @TestDataPath("$PROJECT_ROOT")
     public class Multiplatform {
       @Test
+      @TestMetadata("abstractEnumInIr.kt")
+      public void testAbstractEnumInIr() {
+        runTest("compiler/testData/diagnostics/tests/multiplatform/abstractEnumInIr.kt");
+      }
+
+      @Test
       @TestMetadata("actualClassDelegationWithImplicitType.kt")
       public void testActualClassDelegationWithImplicitType() {
         runTest("compiler/testData/diagnostics/tests/multiplatform/actualClassDelegationWithImplicitType.kt");