Move deferred annotation processing to the fixed point

This is required to ensure that conditional edges with annotation
constraints are applied to the final keep info. This is a prerequisite
for more precise native interpretation of keep annotations.

Bug: b/323816623
Change-Id: I52977cd698b9b58630ae8486277682e5255dcc19
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 0b345b0..25a690e 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -442,6 +442,9 @@
    */
   private final Set<DexMethod> recordFieldValuesReferences = Sets.newIdentityHashSet();
 
+  /** Set of annotations that are live (needed for deferred (re)processing). */
+  private final Set<DexType> liveAnnotations = Sets.newIdentityHashSet();
+
   /**
    * A map from annotation classes to annotations that need to be processed should the classes ever
    * become live.
@@ -2327,11 +2330,8 @@
 
     processAnnotations(clazz);
 
-    // If this type has deferred annotations, we have to process those now, too.
     if (clazz.isAnnotation()) {
-      processDeferredAnnotations(clazz, deferredAnnotations, AnnotatedKind::from);
-      processDeferredAnnotations(
-          clazz, deferredParameterAnnotations, annotatedItem -> AnnotatedKind.PARAMETER);
+      liveAnnotations.add(clazz.getType());
     }
 
     compatEnqueueHolderIfDependentNonStaticMember(
@@ -2341,20 +2341,21 @@
   }
 
   private void processDeferredAnnotations(
-      DexProgramClass clazz,
       Map<DexType, Map<DexAnnotation, List<ProgramDefinition>>> deferredAnnotations,
       Function<ProgramDefinition, AnnotatedKind> kindProvider) {
-    Map<DexAnnotation, List<ProgramDefinition>> annotations =
-        deferredAnnotations.remove(clazz.getType());
-    if (annotations != null) {
-      assert annotations.keySet().stream()
-          .allMatch(annotation -> clazz.getType().isIdenticalTo(annotation.getAnnotationType()));
-      annotations.forEach(
-          (annotation, annotatedItems) ->
-              annotatedItems.forEach(
-                  annotatedItem ->
-                      processAnnotation(
-                          annotatedItem, annotation, kindProvider.apply(annotatedItem))));
+    for (DexType annotationType : liveAnnotations) {
+      Map<DexAnnotation, List<ProgramDefinition>> annotations =
+          deferredAnnotations.remove(annotationType);
+      if (annotations != null) {
+        assert annotations.keySet().stream()
+            .allMatch(annotation -> annotationType.isIdenticalTo(annotation.getAnnotationType()));
+        annotations.forEach(
+            (annotation, annotatedItems) ->
+                annotatedItems.forEach(
+                    annotatedItem ->
+                        processAnnotation(
+                            annotatedItem, annotation, kindProvider.apply(annotatedItem))));
+      }
     }
   }
 
@@ -4732,6 +4733,11 @@
           }
         }
 
+        // Process all deferred annotations.
+        processDeferredAnnotations(deferredAnnotations, AnnotatedKind::from);
+        processDeferredAnnotations(
+            deferredParameterAnnotations, annotatedItem -> AnnotatedKind.PARAMETER);
+
         // Continue fix-point processing while there are additional work items to ensure items that
         // are passed to Java reflections are traced.
         if (!pendingReflectiveUses.isEmpty()) {