Allow R class fields that don't have a value

We saw issues with this in coverage runs in platform

Bug: 287398085
Change-Id: I554c3d5820ae01f1b309a98ea43f72b1c7245497
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/ResourceAccessAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/ResourceAccessAnalysis.java
index b39eb30..01e5f1e 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/ResourceAccessAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/ResourceAccessAnalysis.java
@@ -80,8 +80,12 @@
       assert fieldToValueMapping.containsKey(holderType);
       RClassFieldToValueStore rClassFieldToValueStore = fieldToValueMapping.get(holderType);
       IntList integers = rClassFieldToValueStore.valueMapping.get(field);
-      for (Integer integer : integers) {
-        resourceShrinkerState.trace(integer);
+      // The R class can have fields injected, e.g., by jacoco, we don't have resource values for
+      // these.
+      if (integers != null) {
+        for (Integer integer : integers) {
+          resourceShrinkerState.trace(integer);
+        }
       }
     }
   }
diff --git a/src/test/java/com/android/tools/r8/androidresources/RClassWithNonIDFieldTest.java b/src/test/java/com/android/tools/r8/androidresources/RClassWithNonIDFieldTest.java
new file mode 100644
index 0000000..8cac122
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/androidresources/RClassWithNonIDFieldTest.java
@@ -0,0 +1,80 @@
+// Copyright (c) 2024, 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.androidresources;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResource;
+import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.AndroidTestResourceBuilder;
+import com.google.common.collect.ImmutableList;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class RClassWithNonIDFieldTest extends TestBase {
+
+  @Parameter(0)
+  public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection parameters() {
+    return getTestParameters().withDefaultDexRuntime().withAllApiLevels().build();
+  }
+
+  public static AndroidTestResource getTestResources(TemporaryFolder temp) throws Exception {
+    return new AndroidTestResourceBuilder()
+        .withSimpleManifestAndAppNameString()
+        .addRClassInitializeWithDefaultValues(R.string.class)
+        .build(temp);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    // We test the non id field type by simply passing the standard test resources but ignoring
+    // the aapt generated R class, instead we pass directly the R class from this file, which
+    // have no real resource references, but does have a non integer field.
+    testForR8(parameters.getBackend())
+        .setMinApi(parameters)
+        .addProgramClasses(FooBar.class)
+        .addAndroidResources(
+            getTestResources(temp),
+            temp.newFile("resout.zip").toPath(),
+            ImmutableList.of(ToolHelper.getClassAsBytes(R.string.class)))
+        .addKeepMainRule(FooBar.class)
+        .enableOptimizedShrinking()
+        .compile()
+        .inspectShrunkenResources(
+            resourceTableInspector -> {
+              // We explicitly do not have any resources traced since we don't use the aapt
+              // R class file.
+              resourceTableInspector.assertDoesNotContainResourceWithName("string", "foo");
+            })
+        .run(parameters.getRuntime(), FooBar.class)
+        .assertSuccessWithOutputLines("bar");
+  }
+
+  public static class FooBar {
+    public static void main(String[] args) {
+      if (System.currentTimeMillis() == 0) {
+        System.out.println(R.string.foo);
+      }
+      if (R.string.nonResource != null) {
+        System.out.println("bar");
+      }
+    }
+  }
+
+  public static class R {
+    public static class string {
+      private static Object nonResource = new Object();
+      public static int foo = 0x7f110004;
+    }
+  }
+}
diff --git a/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java b/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
index a9c431a..5f68743 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
@@ -3,9 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8;
 
-import static com.android.tools.r8.dexsplitter.SplitterTestBase.simpleSplitProvider;
-import static com.android.tools.r8.dexsplitter.SplitterTestBase.splitWithNonJavaFile;
-import static com.android.tools.r8.utils.codeinspector.Matchers.proguardConfigurationRuleDoesNotMatch;
 
 import com.android.tools.r8.R8Command.Builder;
 import com.android.tools.r8.TestBase.Backend;
@@ -945,6 +942,12 @@
   }
 
   public T addAndroidResources(AndroidTestResource testResource, Path output) throws IOException {
+    List<byte[]> classFileData = testResource.getRClass().getClassFileData();
+    return addAndroidResources(testResource, output, classFileData);
+  }
+
+  public T addAndroidResources(
+      AndroidTestResource testResource, Path output, List<byte[]> classFileData) {
     Path resources = testResource.getResourceZip();
     resourceShrinkerOutput = output;
     getBuilder()
@@ -952,7 +955,8 @@
             new ArchiveProtoAndroidResourceProvider(resources, new PathOrigin(resources)));
     getBuilder()
         .setAndroidResourceConsumer(new ArchiveProtoAndroidResourceConsumer(output, resources));
-    return addProgramClassFileData(testResource.getRClass().getClassFileData());
+
+    return addProgramClassFileData(classFileData);
   }
 
   public T setAndroidResourcesFromPath(Path input) throws IOException {