[Metadata] Check if inline function has default arguments

Bug: 211113454
Change-Id: I5b70568a88cc3cd0d1bb7b2bb09fcd8d78c32eb3
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
index 9e79ee0..5022d48 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinDeclarationContainerInfo.java
@@ -5,6 +5,7 @@
 package com.android.tools.r8.kotlin;
 
 import static com.android.tools.r8.kotlin.KotlinMetadataUtils.isValidMethodDescriptor;
+import static com.android.tools.r8.kotlin.KotlinMetadataUtils.toDefaultJvmMethodSignature;
 import static com.android.tools.r8.utils.FunctionUtils.forEachApply;
 
 import com.android.tools.r8.graph.AppView;
@@ -18,6 +19,8 @@
 import com.android.tools.r8.shaking.EnqueuerMetadataTraceable;
 import com.android.tools.r8.utils.Reporter;
 import com.google.common.collect.ImmutableList;
+import com.google.common.math.IntMath;
+import java.math.RoundingMode;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -87,7 +90,7 @@
         }
         continue;
       }
-      keepIfInline(kmFunction.getFlags(), method, keepByteCode);
+      keepIfInline(kmFunction.getFlags(), method, signature, methodSignatureMap, keepByteCode);
       method.setKotlinMemberInfo(kotlinFunctionInfo);
       originalAssignmentTracker.add(method.getReference());
     }
@@ -138,8 +141,24 @@
   }
 
   private static void keepIfInline(
-      int flags, DexEncodedMethod method, Consumer<DexEncodedMethod> keepByteCode) {
+      int flags,
+      DexEncodedMethod method,
+      JvmMethodSignature signature,
+      Map<String, DexEncodedMethod> methodSignatureMap,
+      Consumer<DexEncodedMethod> keepByteCode) {
     if (Flags.IS_INLINE.get(flags)) {
+      // Check if we can find a default method. If there are more than 32 arguments another int
+      // index will be added to the default method.
+      for (int i = 1;
+          i <= IntMath.divide(method.getParameters().size(), 32, RoundingMode.CEILING);
+          i++) {
+        DexEncodedMethod defaultValueMethod =
+            methodSignatureMap.get(toDefaultJvmMethodSignature(signature, i).toString());
+        if (defaultValueMethod != null) {
+          keepByteCode.accept(defaultValueMethod);
+          return;
+        }
+      }
       keepByteCode.accept(method);
     }
   }
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
index 2d6f39a..1d927fe 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataUtils.java
@@ -21,6 +21,7 @@
 import com.android.tools.r8.shaking.ProguardKeepRuleType;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.Pair;
+import com.google.common.base.Strings;
 import kotlinx.metadata.KmExtensionType;
 import kotlinx.metadata.KmProperty;
 import kotlinx.metadata.KmPropertyExtensionVisitor;
@@ -99,13 +100,21 @@
     return new JvmMethodSignature(method.name.toString(), descBuilder.toString());
   }
 
+  static JvmMethodSignature toDefaultJvmMethodSignature(
+      JvmMethodSignature methodSignature, int intArguments) {
+    return new JvmMethodSignature(
+        methodSignature.getName() + "$default",
+        methodSignature
+            .getDesc()
+            .replace(")", Strings.repeat("I", intArguments) + "Ljava/lang/Object;)"));
+  }
+
   static class KmPropertyProcessor {
     private JvmFieldSignature fieldSignature = null;
     // Custom getter via @get:JvmName("..."). Otherwise, null.
     private JvmMethodSignature getterSignature = null;
     // Custom getter via @set:JvmName("..."). Otherwise, null.
     private JvmMethodSignature setterSignature = null;
-
     KmPropertyProcessor(KmProperty kmProperty) {
       kmProperty.accept(
           new KmPropertyVisitor() {
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteCrossinlineBlockTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteCrossinlineBlockTest.java
index 63197d4..258230a 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteCrossinlineBlockTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteCrossinlineBlockTest.java
@@ -6,18 +6,13 @@
 
 import static com.android.tools.r8.ToolHelper.getKotlinAnnotationJar;
 import static com.android.tools.r8.ToolHelper.getKotlinStdlibJar;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertNotEquals;
 
-import com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion;
 import com.android.tools.r8.KotlinTestParameters;
 import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.ToolHelper.ProcessResult;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.StringUtils;
 import java.nio.file.Path;
 import java.util.Collection;
-import org.hamcrest.CoreMatchers;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -25,7 +20,11 @@
 @RunWith(Parameterized.class)
 public class MetadataRewriteCrossinlineBlockTest extends KotlinMetadataTestBase {
 
-  private final String EXPECTED = StringUtils.lines("foo");
+  private final String EXPECTED =
+      StringUtils.lines(
+          "foo", "42", "42", "0", "42", "42", "42", "42", "42", "42", "42", "42", "42", "42", "42",
+          "42", "42", "42", "42", "42", "42", "42", "42", "42", "42", "42", "42", "42", "42", "42",
+          "42", "42", "42", "42");
   private static final String PKG_LIB = PKG + ".crossinline_block_lib";
   private static final String PKG_APP = PKG + ".crossinline_block_app";
 
@@ -74,26 +73,18 @@
             .addKeepAllAttributes()
             .compile()
             .writeToZip();
-    ProcessResult kotlinCompileResult =
+    Path output =
         kotlinc(parameters.getRuntime().asCf(), kotlinc, targetVersion)
             .addClasspathFiles(libJar)
             .addSourceFiles(
                 getKotlinFileInTest(DescriptorUtils.getBinaryNameFromJavaType(PKG_APP), "main"))
             .setOutputPath(temp.newFolder().toPath())
             .enableAssertions()
-            .compileRaw();
-    // TODO(b/211113454): This compilation should not fail.
-    assertNotEquals(0, kotlinCompileResult.exitCode);
-    if (kotlinc.is(KotlinCompilerVersion.KOTLINC_1_3_72)) {
-      assertThat(
-          kotlinCompileResult.stderr,
-          CoreMatchers.containsString(
-              "java.lang.AssertionError: 'checkParameterIsNotNull' should be invoked on local"));
-    } else {
-      assertThat(
-          kotlinCompileResult.stderr,
-          CoreMatchers.containsString(
-              "java.lang.AssertionError: 'checkNotNullParameter' should be invoked on local"));
-    }
+            .compile();
+    testForJvm()
+        .addRunClasspathFiles(getKotlinStdlibJar(kotlinc), libJar)
+        .addClasspath(output)
+        .run(parameters.getRuntime(), PKG_APP + ".MainKt")
+        .assertSuccessWithOutput(EXPECTED);
   }
 }
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/crossinline_block_app/main.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/crossinline_block_app/main.kt
index c658ae8..b349233 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/crossinline_block_app/main.kt
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/crossinline_block_app/main.kt
@@ -4,11 +4,13 @@
 
 package com.android.tools.r8.kotlin.metadata.crossinline_block_app
 
+import com.android.tools.r8.kotlin.metadata.crossinline_block_lib.bar
 import com.android.tools.r8.kotlin.metadata.crossinline_block_lib.foo
 
 fun main(args : Array<String>) {
   if (args.isEmpty()) {
     call("foo")
+    bar(bar3 = 0)
   } else {
     call("bar")
   }
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/crossinline_block_lib/lib.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/crossinline_block_lib/lib.kt
index 075be3e..d7efaaf 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/crossinline_block_lib/lib.kt
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/crossinline_block_lib/lib.kt
@@ -10,3 +10,73 @@
 ) {
   block()
 }
+
+public inline fun bar(
+  bar1: Int = 42,
+  bar2: Int = 42,
+  bar3: Int = 42,
+  bar4: Int = 42,
+  bar5: Int = 42,
+  bar6: Int = 42,
+  bar7: Int = 42,
+  bar8: Int = 42,
+  bar9: Int = 42,
+  bar10: Int = 42,
+  bar11: Int = 42,
+  bar12: Int = 42,
+  bar13: Int = 42,
+  bar14: Int = 42,
+  bar15: Int = 42,
+  bar16: Int = 42,
+  bar17: Int = 42,
+  bar18: Int = 42,
+  bar19: Int = 42,
+  bar20: Int = 42,
+  bar21: Int = 42,
+  bar22: Int = 42,
+  bar23: Int = 42,
+  bar24: Int = 42,
+  bar25: Int = 42,
+  bar26: Int = 42,
+  bar27: Int = 42,
+  bar28: Int = 42,
+  bar29: Int = 42,
+  bar30: Int = 42,
+  bar31: Int = 42,
+  bar32: Int = 42,
+  bar33: Int = 42
+) {
+  println(bar1)
+  println(bar2)
+  println(bar3)
+  println(bar4)
+  println(bar5)
+  println(bar6)
+  println(bar7)
+  println(bar8)
+  println(bar9)
+  println(bar10)
+  println(bar11)
+  println(bar12)
+  println(bar13)
+  println(bar14)
+  println(bar15)
+  println(bar16)
+  println(bar17)
+  println(bar18)
+  println(bar19)
+  println(bar20)
+  println(bar21)
+  println(bar22)
+  println(bar23)
+  println(bar24)
+  println(bar25)
+  println(bar26)
+  println(bar27)
+  println(bar28)
+  println(bar29)
+  println(bar30)
+  println(bar31)
+  println(bar32)
+  println(bar33)
+}
\ No newline at end of file