Ensure a SourceFile attribute for synthesized code
For now use a fixed value if the synthetic code did not explicitly
add a SourceFile attribute.
Bug: 187491007
Bug: 187672208
Change-Id: I0bbe123d7dca72dcf0a7546e831a384b43752c16
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 2d0e429..ce36598 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -177,6 +177,10 @@
return sourceFile;
}
+ public void setSourceFile(DexString sourceFile) {
+ this.sourceFile = sourceFile;
+ }
+
public Iterable<DexEncodedField> fields() {
return fields(Predicates.alwaysTrue());
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index de86111..a63a1e7 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
@@ -321,6 +322,13 @@
return true;
}
+ private static void ensureSourceFile(
+ DexProgramClass externalSyntheticClass, DexString syntheticSourceFileName) {
+ if (externalSyntheticClass.getSourceFile() == null) {
+ externalSyntheticClass.setSourceFile(syntheticSourceFileName);
+ }
+ }
+
private static DexApplication buildLensAndProgram(
AppView<?> appView,
Map<DexType, EquivalenceGroup<SyntheticMethodDefinition>> syntheticMethodGroups,
@@ -415,6 +423,11 @@
application = builder.build();
}
+ DexString syntheticSourceFileName =
+ appView.enableWholeProgramOptimizations()
+ ? appView.dexItemFactory().createString("R8$$SyntheticClass")
+ : appView.dexItemFactory().createString("D8$$SyntheticClass");
+
// Add the synthesized from after repackaging which changed class definitions.
final DexApplication appForLookup = application;
syntheticClassGroups.forEach(
@@ -422,6 +435,7 @@
DexProgramClass externalSyntheticClass = appForLookup.programDefinitionFor(syntheticType);
assert externalSyntheticClass != null
: "Expected definition for " + syntheticType.getTypeName();
+ ensureSourceFile(externalSyntheticClass, syntheticSourceFileName);
SyntheticProgramClassDefinition representative = syntheticGroup.getRepresentative();
addFinalSyntheticClass.accept(
externalSyntheticClass,
@@ -433,6 +447,7 @@
syntheticMethodGroups.forEach(
(syntheticType, syntheticGroup) -> {
DexProgramClass externalSyntheticClass = appForLookup.programDefinitionFor(syntheticType);
+ ensureSourceFile(externalSyntheticClass, syntheticSourceFileName);
SyntheticMethodDefinition representative = syntheticGroup.getRepresentative();
assert externalSyntheticClass.getMethodCollection().size() == 1;
assert externalSyntheticClass.getMethodCollection().hasDirectMethods();
diff --git a/src/test/java/com/android/tools/r8/desugar/lambdas/LambdaInStacktraceTest.java b/src/test/java/com/android/tools/r8/desugar/lambdas/LambdaInStacktraceTest.java
index 3a923e0..640796d 100644
--- a/src/test/java/com/android/tools/r8/desugar/lambdas/LambdaInStacktraceTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/lambdas/LambdaInStacktraceTest.java
@@ -3,11 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.desugar.lambdas;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.utils.StringUtils;
import java.util.ArrayList;
import java.util.List;
@@ -35,6 +37,17 @@
StringUtils.lines(
"getStacktraceWithFileNames(" + fileName + ")",
"lambda$main$0(" + fileName + ")",
+ "call(D8$$SyntheticClass)",
+ "main(" + fileName + ")",
+ "getStacktraceWithFileNames(" + fileName + ")",
+ "lambda$main$1(" + fileName + ")",
+ "call(D8$$SyntheticClass)",
+ "main(" + fileName + ")");
+
+ static final String EXPECTED_D8_ANDROID_O =
+ StringUtils.lines(
+ "getStacktraceWithFileNames(" + fileName + ")",
+ "lambda$main$0(" + fileName + ")",
"call(NULL)",
"main(" + fileName + ")",
"getStacktraceWithFileNames(" + fileName + ")",
@@ -43,6 +56,7 @@
"main(" + fileName + ")");
private final TestParameters parameters;
+ private final boolean isAndroidOOrLater;
private final boolean isDalvik;
@Parameterized.Parameters(name = "{0}")
@@ -53,6 +67,9 @@
public LambdaInStacktraceTest(TestParameters parameters) {
this.parameters = parameters;
isDalvik = parameters.isDexRuntime() && parameters.getDexRuntimeVersion().isDalvik();
+ isAndroidOOrLater =
+ parameters.isDexRuntime()
+ && parameters.getDexRuntimeVersion().isNewerThanOrEqual(Version.V8_1_0);
}
@Test
@@ -71,7 +88,26 @@
.addInnerClasses(LambdaInStacktraceTest.class)
.setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), TestRunner.class, Boolean.toString(isDalvik))
- .assertSuccessWithOutput(EXPECTED_D8);
+ .assertSuccessWithOutput(isAndroidOOrLater ? EXPECTED_D8_ANDROID_O : EXPECTED_D8);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ assumeTrue(parameters.getRuntime().isDex());
+ String stdout =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(LambdaInStacktraceTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(TestRunner.class)
+ .addKeepAttributeSourceFile()
+ .addKeepRules("-renamesourcefileattribute SourceFile")
+ .noTreeShaking()
+ .run(parameters.getRuntime(), TestRunner.class, Boolean.toString(isDalvik))
+ .assertSuccess()
+ .getStdOut();
+ assertTrue(
+ StringUtils.splitLines(stdout).stream()
+ .allMatch(s -> s.contains(isAndroidOOrLater ? "NULL" : "SourceFile")));
}
static class TestRunner {