Allow interface classes named package-info without ACC_ABSTRACT
This was already handled on then DEX and R8 case by adding the
ACC_ABSTRACT flag. In D8 Cf to Cf desugaring do a pass through
keeping the interface without ACC_ABSTRACT.
Fixes: b/234792931
Change-Id: Iac39c48dc07beff5448c6765b88b140fa1bfbecf
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index d576801..cdb9762 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -243,8 +243,15 @@
clazz.accessFlags.setSuper();
}
}
+ boolean allowInvalidCfAccessFlags = false;
+ if (clazz
+ .getType()
+ .getDescriptor()
+ .endsWith(appView.dexItemFactory().createString("/package-info;"))) {
+ allowInvalidCfAccessFlags = true;
+ }
int access =
- options.testing.allowInvalidCfAccessFlags
+ allowInvalidCfAccessFlags || options.testing.allowInvalidCfAccessFlags
? clazz.accessFlags.materialize()
: clazz.accessFlags.getAsCfAccessFlags();
if (clazz.isDeprecated()) {
diff --git a/src/test/java/com/android/tools/r8/cf/PackageInfoClassFileWithoutAbstractAccessModifierTest.java b/src/test/java/com/android/tools/r8/cf/PackageInfoClassFileWithoutAbstractAccessModifierTest.java
new file mode 100644
index 0000000..0db0bbf
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/PackageInfoClassFileWithoutAbstractAccessModifierTest.java
@@ -0,0 +1,77 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.cf;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.Matchers;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
+
+@RunWith(Parameterized.class)
+public class PackageInfoClassFileWithoutAbstractAccessModifierTest extends TestBase
+ implements Opcodes {
+
+ @Parameter(0)
+ public TestParameters parameters;
+
+ @Parameter(1)
+ public Backend backend;
+
+ @Parameters(name = "{0}")
+ public static List<Object[]> data() {
+ return buildParameters(getTestParameters().withNoneRuntime().build(), Backend.values());
+ }
+
+ private static final String CLASS_NAME = "it.unimi.dsi.fastutil.package-info";
+
+ private void inspect(CodeInspector inspector, boolean isR8) {
+ ClassSubject packageInfo = inspector.clazz(CLASS_NAME);
+ assertThat(packageInfo, Matchers.isInterface());
+ assertEquals(backend.isDex() || isR8, packageInfo.isAbstract());
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ testForD8(backend)
+ .addProgramClassFileData(dump())
+ .setMinApi(AndroidApiLevel.B)
+ .compile()
+ .inspect(inspector -> inspect(inspector, false));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(backend)
+ .addProgramClassFileData(dump())
+ .addKeepMainRule(CLASS_NAME)
+ .setMinApi(AndroidApiLevel.B)
+ .compile()
+ .inspect(inspector -> inspect(inspector, true));
+ }
+
+ // Some versions of javac would generate package-info class files without ACC_ABSTRACT.
+ // Dump of it/unimi/dsi/fastutil/package-info.class from fastutil-8.5.8.jar.
+ public static byte[] dump() throws Exception {
+ ClassWriter classWriter = new ClassWriter(0);
+ classWriter.visit(
+ V1_5, ACC_INTERFACE, "it/unimi/dsi/fastutil/package-info", null, "java/lang/Object", null);
+ classWriter.visitSource("package-info.java", null);
+ classWriter.visitEnd();
+ return classWriter.toByteArray();
+ }
+}