Reland "Set supported CF version to V15"

This reverts commit fc34eccb08694e5479755b819451d95e4228d29c.

Bug: 141587937
Change-Id: I65a35087c7c50410bcd5d0b17fcf2242c4da826c
diff --git a/src/main/java/com/android/tools/r8/cf/CfVersion.java b/src/main/java/com/android/tools/r8/cf/CfVersion.java
index 7a68742..a69cc03 100644
--- a/src/main/java/com/android/tools/r8/cf/CfVersion.java
+++ b/src/main/java/com/android/tools/r8/cf/CfVersion.java
@@ -23,6 +23,10 @@
   public static final CfVersion V9 = new CfVersion(Opcodes.V9);
   public static final CfVersion V10 = new CfVersion(Opcodes.V10);
   public static final CfVersion V11 = new CfVersion(Opcodes.V11);
+  public static final CfVersion V12 = new CfVersion(Opcodes.V12);
+  public static final CfVersion V13 = new CfVersion(Opcodes.V13);
+  public static final CfVersion V14 = new CfVersion(Opcodes.V14);
+  public static final CfVersion V15 = new CfVersion(Opcodes.V15);
 
   private final int version;
 
diff --git a/src/main/java/com/android/tools/r8/errors/ExperimentalClassFileVersionDiagnostic.java b/src/main/java/com/android/tools/r8/errors/ExperimentalClassFileVersionDiagnostic.java
new file mode 100644
index 0000000..953afb2
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/errors/ExperimentalClassFileVersionDiagnostic.java
@@ -0,0 +1,35 @@
+// Copyright (c) 2020, 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.errors;
+
+import com.android.tools.r8.Diagnostic;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.position.Position;
+
+public class ExperimentalClassFileVersionDiagnostic implements Diagnostic {
+
+  private final String message;
+  private final Origin origin;
+
+  public ExperimentalClassFileVersionDiagnostic(Origin origin, String message) {
+    this.origin = origin;
+    this.message = message;
+  }
+
+  @Override
+  public Origin getOrigin() {
+    return origin;
+  }
+
+  @Override
+  public Position getPosition() {
+    return Position.UNKNOWN;
+  }
+
+  @Override
+  public String getDiagnosticMessage() {
+    return message;
+  }
+}
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 0902a45..fabdde7 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -57,12 +57,12 @@
 import java.util.function.Consumer;
 import java.util.zip.CRC32;
 import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.Attribute;
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.FieldVisitor;
 import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.RecordComponentVisitor;
 import org.objectweb.asm.Type;
 import org.objectweb.asm.TypePath;
 
@@ -300,6 +300,17 @@
     }
 
     @Override
+    public RecordComponentVisitor visitRecordComponent(
+        String name, String descriptor, String signature) {
+      throw new CompilationError("Records are not supported", origin);
+    }
+
+    @Override
+    public void visitPermittedSubclass(String permittedSubclass) {
+      throw new CompilationError("Sealed classes are not supported", origin);
+    }
+
+    @Override
     public void visit(
         int rawVersion,
         int access,
@@ -311,6 +322,9 @@
       if (InternalOptions.SUPPORTED_CF_VERSION.isLessThan(version)) {
         throw new CompilationError("Unsupported class file version: " + version, origin);
       }
+      if (version.isGreaterThanOrEqualTo(InternalOptions.EXPERIMENTAL_CF_VERSION)) {
+        application.options.warningExperimentalClassFileVersion(origin);
+      }
       this.deprecated = AsmUtils.isDeprecated(access);
       accessFlags = ClassAccessFlags.fromCfAccessFlags(cleanAccessFlags(access));
       type = application.getTypeFromName(name);
@@ -400,11 +414,6 @@
     }
 
     @Override
-    public void visitAttribute(Attribute attr) {
-      // Unknown attribute must only be ignored
-    }
-
-    @Override
     public void visitEnd() {
       if (defaultAnnotations != null) {
         addAnnotation(DexAnnotation.createAnnotationDefaultAnnotation(
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 6c0cc5b..175a39e 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -21,6 +21,7 @@
 import com.android.tools.r8.dex.Marker.Backend;
 import com.android.tools.r8.dex.Marker.Tool;
 import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.errors.ExperimentalClassFileVersionDiagnostic;
 import com.android.tools.r8.errors.IncompleteNestNestDesugarDiagnosic;
 import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
 import com.android.tools.r8.errors.InvalidDebugInfoException;
@@ -108,11 +109,13 @@
     ON
   }
 
-  public static final CfVersion SUPPORTED_CF_VERSION = CfVersion.V11;
+  public static final CfVersion SUPPORTED_CF_VERSION = CfVersion.V15;
+  public static final CfVersion EXPERIMENTAL_CF_VERSION = CfVersion.V12;
+
   public static final int SUPPORTED_DEX_VERSION =
       AndroidApiLevel.LATEST.getDexVersion().getIntValue();
 
-  public static final int ASM_VERSION = Opcodes.ASM7;
+  public static final int ASM_VERSION = Opcodes.ASM9;
 
   public final DexItemFactory itemFactory;
 
@@ -1044,6 +1047,23 @@
     reporter.warning(new StringDiagnostic(message.toString(), origin));
   }
 
+  private final Box<Boolean> reportedExperimentClassFileVersion = new Box<>(false);
+
+  public void warningExperimentalClassFileVersion(Origin origin) {
+    synchronized (reportedExperimentClassFileVersion) {
+      if (reportedExperimentClassFileVersion.get()) {
+        return;
+      }
+      reportedExperimentClassFileVersion.set(true);
+      reporter.warning(
+          new ExperimentalClassFileVersionDiagnostic(
+              origin,
+              "One or more classes has class file version >= "
+                  + EXPERIMENTAL_CF_VERSION.major()
+                  + " which is not officially supported."));
+    }
+  }
+
   public boolean printWarnings() {
     boolean printed = false;
     boolean printOutdatedToolchain = false;
diff --git a/src/test/java/com/android/tools/r8/TestParametersBuilder.java b/src/test/java/com/android/tools/r8/TestParametersBuilder.java
index f93d6d6..9b84425 100644
--- a/src/test/java/com/android/tools/r8/TestParametersBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestParametersBuilder.java
@@ -19,10 +19,6 @@
 
 public class TestParametersBuilder {
 
-  // Static computation of VMs configured as available by the testing invocation.
-  private static final List<TestRuntime> availableRuntimes =
-      getAvailableRuntimes().collect(Collectors.toList());
-
   // Predicate describing which test parameters are applicable to the test.
   // Built via the methods found below. Defaults to no applicable parameters, i.e., the emtpy set.
   private Predicate<TestParameters> filter = param -> false;
@@ -154,6 +150,7 @@
 
   private Predicate<AndroidApiLevel> apiLevelFilter = param -> false;
   private List<AndroidApiLevel> explicitApiLevels = new ArrayList<>();
+  private List<TestRuntime> customRuntimes = new ArrayList<>();
 
   private TestParametersBuilder withApiFilter(Predicate<AndroidApiLevel> filter) {
     enableApiLevels = true;
@@ -195,13 +192,23 @@
     return withApiFilter(api -> api.getLevel() < endExclusive.getLevel());
   }
 
+  public TestParametersBuilder withCustomRuntime(TestRuntime runtime) {
+    assert getUnfilteredAvailableRuntimes().noneMatch(r -> r == runtime);
+    customRuntimes.add(runtime);
+    return this;
+  }
+
   public TestParametersCollection build() {
     assert !enableApiLevels || enableApiLevelsForCf || hasDexRuntimeFilter;
-    return new TestParametersCollection(
+    List<TestParameters> availableParameters =
         getAvailableRuntimes()
             .flatMap(this::createParameters)
             .filter(filter)
-            .collect(Collectors.toList()));
+            .collect(Collectors.toList());
+    List<TestParameters> customParameters =
+        customRuntimes.stream().flatMap(this::createParameters).collect(Collectors.toList());
+    availableParameters.addAll(customParameters);
+    return new TestParametersCollection(availableParameters);
   }
 
   public Stream<TestParameters> createParameters(TestRuntime runtime) {
diff --git a/src/test/java/com/android/tools/r8/desugar/records/RecordsAttributeTest.java b/src/test/java/com/android/tools/r8/desugar/records/RecordsAttributeTest.java
index 723dfe6..831c426 100644
--- a/src/test/java/com/android/tools/r8/desugar/records/RecordsAttributeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/records/RecordsAttributeTest.java
@@ -7,12 +7,13 @@
 import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage;
 import static org.hamcrest.CoreMatchers.containsString;
 import static org.junit.Assert.assertThrows;
+import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestRuntime;
+import com.android.tools.r8.TestRuntime.CfRuntime;
 import com.android.tools.r8.examples.jdk15.Records;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import java.util.List;
@@ -25,23 +26,29 @@
 public class RecordsAttributeTest extends TestBase {
 
   private final Backend backend;
+  private final TestParameters parameters;
 
   @Parameters(name = "{0}")
   public static List<Object[]> data() {
-    return buildParameters(getTestParameters().withNoneRuntime().build(), Backend.values());
+    // TODO(b/174431251): This should be replaced with .withCfRuntimes(start = jdk15).
+    return buildParameters(
+        getTestParameters().withCustomRuntime(CfRuntime.getCheckedInJdk15()).build(),
+        Backend.values());
   }
 
   public RecordsAttributeTest(TestParameters parameters, Backend backend) {
+    this.parameters = parameters;
     this.backend = backend;
   }
 
   @Test
   public void testJvm() throws Exception {
+    assumeFalse(parameters.isNoneRuntime());
     assumeTrue(backend == Backend.CF);
     testForJvm()
         .addRunClasspathFiles(Records.jar())
         .addVmArguments("--enable-preview")
-        .run(TestRuntime.getCheckedInJdk15(), Records.Main.typeName())
+        .run(parameters.getRuntime(), Records.Main.typeName())
         .assertSuccessWithOutputLines("Jane Doe", "42");
   }
 
@@ -56,7 +63,7 @@
               .compileWithExpectedDiagnostics(
                   diagnostics -> {
                     diagnostics.assertErrorThatMatches(
-                        diagnosticMessage(containsString("Unsupported class file version: 59")));
+                        diagnosticMessage(containsString("Records are not supported")));
                   });
         });
   }
@@ -73,7 +80,7 @@
               .compileWithExpectedDiagnostics(
                   diagnostics -> {
                     diagnostics.assertErrorThatMatches(
-                        diagnosticMessage(containsString("Unsupported class file version: 59")));
+                        diagnosticMessage(containsString("Records are not supported")));
                   });
         });
   }
diff --git a/src/test/java/com/android/tools/r8/desugar/sealed/SealedAttributeTest.java b/src/test/java/com/android/tools/r8/desugar/sealed/SealedAttributeTest.java
index 8aa79eb..48b29e7 100644
--- a/src/test/java/com/android/tools/r8/desugar/sealed/SealedAttributeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/sealed/SealedAttributeTest.java
@@ -28,7 +28,10 @@
 
   @Parameters(name = "{0}")
   public static List<Object[]> data() {
-    return buildParameters(getTestParameters().withNoneRuntime().build(), Backend.values());
+    // TODO(b/174431251): This should be replaced with .withCfRuntimes(start = jdk15).
+    return buildParameters(
+        getTestParameters().withCustomRuntime(TestRuntime.getCheckedInJdk15()).build(),
+        Backend.values());
   }
 
   public SealedAttributeTest(TestParameters parameters, Backend backend) {
@@ -56,7 +59,7 @@
               .compileWithExpectedDiagnostics(
                   diagnostics -> {
                     diagnostics.assertErrorThatMatches(
-                        diagnosticMessage(containsString("Unsupported class file version: 59")));
+                        diagnosticMessage(containsString("Sealed classes are not supported")));
                   });
         });
   }
@@ -73,7 +76,7 @@
               .compileWithExpectedDiagnostics(
                   diagnostics -> {
                     diagnostics.assertErrorThatMatches(
-                        diagnosticMessage(containsString("Unsupported class file version: 59")));
+                        diagnosticMessage(containsString("Sealed classes are not supported")));
                   });
         });
   }
diff --git a/tools/test.py b/tools/test.py
index 0c70124..cf14685 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -156,6 +156,11 @@
       '--print-obfuscated-stacktraces', '--print_obfuscated_stacktraces',
       default=False, action='store_true',
       help='Print the obfuscated stacktraces')
+  result.add_option(
+      '--debug-agent', '--debug_agent',
+      help='Enable Java debug agent and suspend compilation (default disabled)',
+      default=False,
+      action='store_true')
   return result.parse_args()
 
 def archive_failures():
@@ -253,6 +258,8 @@
   if options.worktree:
     gradle_args.append('-g=' + os.path.join(utils.REPO_ROOT, ".gradle_user_home"))
     gradle_args.append('--no-daemon')
+  if options.debug_agent:
+    gradle_args.append('--no-daemon')
 
   # Build an R8 with dependencies for bootstrapping tests before adding test sources.
   gradle_args.append('r8WithDeps')
@@ -263,6 +270,8 @@
   # Add Gradle tasks
   gradle_args.append('cleanTest')
   gradle_args.append('test')
+  if options.debug_agent:
+    gradle_args.append('--debug-jvm')
   if options.fail_fast:
     gradle_args.append('--fail-fast')
   if options.failed: