Always allow package-info "interface" without abstract flag
Some build tools have been seen to produce this.
Change-Id: I6a8b1631c1af1a2b8cbe72039a723064dac5d401
diff --git a/src/main/java/com/android/tools/r8/dex/DexParser.java b/src/main/java/com/android/tools/r8/dex/DexParser.java
index 4524505..8042a1a 100644
--- a/src/main/java/com/android/tools/r8/dex/DexParser.java
+++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -649,7 +649,7 @@
ClassAccessFlags flags = ClassAccessFlags.fromDexAccessFlags(accessFlags[i]);
// Check if constraints from
// https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1 are met.
- if (!flags.areValid(Constants.CORRESPONDING_CLASS_FILE_VERSION)) {
+ if (!flags.areValid(Constants.CORRESPONDING_CLASS_FILE_VERSION, false)) {
throw new CompilationError("Class " + type.toSourceString()
+ " has illegal access flags. Found: " + flags, origin);
}
diff --git a/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
index 0111aa1..4fce492 100644
--- a/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/ClassAccessFlags.java
@@ -92,15 +92,16 @@
* Checks whether the constraints from
* https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1 are met.
*/
- public boolean areValid(int majorVersion) {
+ public boolean areValid(int majorVersion, boolean isPackageInfo) {
if (isInterface()) {
// We ignore the super flags prior to JDK 9, as so did the VM.
if ((majorVersion >= 53) && isSuper()) {
return false;
}
- // We require interfaces to be abstract from JDK 7 onwards. Old versions of javac seem to
- // have produced package-info classes that are interfaces but not abstract.
- if ((majorVersion >= 51) && (!isAbstract())) {
+ // We require interfaces to be abstract - except for package-info classes - as both old
+ // versions of javac and other tools can produce package-info classes that are interfaces but
+ // not abstract.
+ if (!isAbstract() && !isPackageInfo) {
return false;
}
return !isFinal() && !isEnum();
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index 247f790..a1125af 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -244,6 +244,24 @@
: new EnclosingMethodAttribute(application.getMethod(ownerType, name, desc));
}
+ private String illegalClassFilePrefix(ClassAccessFlags accessFlags, String name) {
+ return "Illegal class file: "
+ + (accessFlags.isInterface() ? "Interface" : "Class")
+ + " "
+ + name;
+ }
+
+ private String illegalClassFilePostfix(int version) {
+ return "Class file version " + version;
+ }
+
+ private String illegalClassFileMessage(
+ ClassAccessFlags accessFlags, String name, int version, String message) {
+ return illegalClassFilePrefix(accessFlags, name)
+ + " " + message
+ + ". " + illegalClassFilePostfix(version) + ".";
+ }
+
@Override
public void visit(int version, int access, String name, String signature, String superName,
String[] interfaces) {
@@ -252,18 +270,22 @@
type = application.getTypeFromName(name);
// Check if constraints from
// https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1 are met.
- if (!accessFlags.areValid(getMajorVersion())) {
- throw new CompilationError("Illegal class file: Class " + name
- + " has invalid access flags. Found: " + accessFlags.toString(), origin);
+ if (!accessFlags.areValid(getMajorVersion(), name.endsWith("/package-info"))) {
+ throw new CompilationError(
+ illegalClassFileMessage(accessFlags, name, version,
+ "has invalid access flags. Found: " + accessFlags.toString()), origin);
}
if (superName == null && !name.equals(Constants.JAVA_LANG_OBJECT_NAME)) {
- throw new CompilationError("Illegal class file: Class " + name
- + " is missing a super type.", origin);
+ throw new CompilationError(
+ illegalClassFileMessage(accessFlags, name, version,
+ "is missing a super type"), origin);
}
if (accessFlags.isInterface()
&& !Objects.equals(superName, Constants.JAVA_LANG_OBJECT_NAME)) {
- throw new CompilationError("Illegal class file: Interface " + name
- + " must extend class java.lang.Object. Found: " + Objects.toString(superName), origin);
+ throw new CompilationError(
+ illegalClassFileMessage(accessFlags, name, version,
+ "must extend class java.lang.Object. Found: " + Objects.toString(superName)),
+ origin);
}
assert superName != null || name.equals(Constants.JAVA_LANG_OBJECT_NAME);
superType = superName == null ? null : application.getTypeFromName(superName);