Merge commit '2b04eb482f57225284ee93ea2fe9400031514c20' into dev-release
diff --git a/foo.txt b/foo.txt deleted file mode 100644 index d896812..0000000 --- a/foo.txt +++ /dev/null
@@ -1,25 +0,0 @@ -Caused by: java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.AssertionError - at com.android.tools.r8.dex.a.a(SourceFile:298) - at com.android.tools.r8.dex.a.a(SourceFile:227) - at com.android.tools.r8.dex.a.a(SourceFile:217) - at com.android.tools.r8.dex.a.a(SourceFile:214) - at com.android.tools.r8.ResourceShrinker.run(ResourceShrinker.java:5) - at com.android.builder.dexing.R8ResourceShrinker.runResourceShrinkerAnalysis(r8ResourceShrinker.kt:33) - at com.android.build.gradle.tasks.ResourceUsageAnalyzer.recordClassUsages(ResourceUsageAnalyzer.java:1493) - at com.android.build.gradle.tasks.ResourceUsageAnalyzer.recordClassUsages(ResourceUsageAnalyzer.java:1412) - at com.android.build.gradle.tasks.ResourceUsageAnalyzer.recordClassUsages(ResourceUsageAnalyzer.java:1406) - at com.android.build.gradle.tasks.ResourceUsageAnalyzer.analyze(ResourceUsageAnalyzer.java:288) - at com.android.build.gradle.internal.transforms.ShrinkResourcesTransform.splitAction(ShrinkResourcesTransform.java:317) - at com.android.build.gradle.internal.transforms.ShrinkResourcesTransform.lambda$transform$0(ShrinkResourcesTransform.java:248) - at com.android.build.gradle.internal.scope.BuildElements$ExecutorBasedScheduler$transform$$inlined$forEach$lambda$1.call(BuildElements.kt:121) - at com.android.build.gradle.internal.scope.BuildElements$ExecutorBasedScheduler$transform$$inlined$forEach$lambda$1.call(BuildElements.kt:110) -Caused by: java.util.concurrent.ExecutionException: java.lang.AssertionError - at com.android.tools.r8.utils.Y0.a(SourceFile:50) - at com.android.tools.r8.dex.a.a(SourceFile:278) - ... 13 more -Caused by: java.lang.AssertionError - at com.android.tools.r8.graph.W$b.a(SourceFile:3) - at com.android.tools.r8.graph.W.o0(SourceFile:6) - at com.android.tools.r8.dex.n.a(SourceFile:707) - at com.android.tools.r8.dex.n.a(SourceFile:989) - at com.android.tools.r8.dex.a$a.a(SourceFile:90)
diff --git a/src/main/java/com/android/tools/r8/ApiLevelException.java b/src/main/java/com/android/tools/r8/ApiLevelException.java index 0ad75c7..d58f0ec 100644 --- a/src/main/java/com/android/tools/r8/ApiLevelException.java +++ b/src/main/java/com/android/tools/r8/ApiLevelException.java
@@ -16,7 +16,7 @@ assert unsupportedFeatures != null; } - private static String makeMessage( + public static String makeMessage( AndroidApiLevel minApiLevel, String unsupportedFeatures, String sourceString) { String message = unsupportedFeatures
diff --git a/src/main/java/com/android/tools/r8/ResourceShrinker.java b/src/main/java/com/android/tools/r8/ResourceShrinker.java index 86859f7..0affffd 100644 --- a/src/main/java/com/android/tools/r8/ResourceShrinker.java +++ b/src/main/java/com/android/tools/r8/ResourceShrinker.java
@@ -102,9 +102,7 @@ @Override InternalOptions getInternalOptions() { - InternalOptions internalOptions = new InternalOptions(); - internalOptions.isRunningDeprecatedResourceShrinker = true; - return internalOptions; + return new InternalOptions(); } }
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 4dba5c6..26dca03 100644 --- a/src/main/java/com/android/tools/r8/dex/DexParser.java +++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -668,14 +668,10 @@ annotationIterator.getNextFor(method), parameterAnnotationsIterator.getNextFor(method), code); - if (accessFlags.isAbstract() - && ensureNonAbstract - && !options.isRunningDeprecatedResourceShrinker) { + if (accessFlags.isAbstract() && ensureNonAbstract) { accessFlags.unsetAbstract(); - encodedMethod = - options.isGeneratingClassFiles() - ? encodedMethod.toEmptyThrowingMethodCf() - : encodedMethod.toEmptyThrowingMethodDex(); + assert !options.isGeneratingClassFiles(); + encodedMethod = encodedMethod.toEmptyThrowingMethodDex(false); } methods[i] = encodedMethod; }
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java index c4040a2..867f32d 100644 --- a/src/main/java/com/android/tools/r8/dex/FileWriter.java +++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -5,10 +5,13 @@ import static com.android.tools.r8.utils.LebUtils.sizeAsUleb128; -import com.android.tools.r8.ApiLevelException; import com.android.tools.r8.ByteBufferProvider; import com.android.tools.r8.code.Instruction; import com.android.tools.r8.errors.CompilationError; +import com.android.tools.r8.errors.DefaultInterfaceMethodDiagnostic; +import com.android.tools.r8.errors.InvokeCustomDiagnostic; +import com.android.tools.r8.errors.PrivateInterfaceMethodDiagnostic; +import com.android.tools.r8.errors.StaticInterfaceMethodDiagnostic; import com.android.tools.r8.graph.DexAnnotation; import com.android.tools.r8.graph.DexAnnotationDirectory; import com.android.tools.r8.graph.DexAnnotationElement; @@ -48,6 +51,7 @@ import com.android.tools.r8.naming.MemberNaming.MethodSignature; import com.android.tools.r8.naming.MemberNaming.Signature; import com.android.tools.r8.naming.NamingLens; +import com.android.tools.r8.position.MethodPosition; import com.android.tools.r8.utils.AndroidApiLevel; import com.android.tools.r8.utils.DexVersion; import com.android.tools.r8.utils.InternalOptions; @@ -267,10 +271,8 @@ } if (method.accessFlags.isStatic()) { if (!options.canUseDefaultAndStaticInterfaceMethods()) { - throw new ApiLevelException( - AndroidApiLevel.N, - "Static interface methods", - method.method.toSourceString()); + throw options.reporter.fatalError( + new StaticInterfaceMethodDiagnostic(new MethodPosition(method.method))); } } else { @@ -280,10 +282,8 @@ } if (!method.accessFlags.isAbstract() && !method.accessFlags.isPrivate() && !options.canUseDefaultAndStaticInterfaceMethods()) { - throw new ApiLevelException( - AndroidApiLevel.N, - "Default interface methods", - method.method.toSourceString()); + throw options.reporter.fatalError( + new DefaultInterfaceMethodDiagnostic(new MethodPosition(method.method))); } } @@ -291,10 +291,8 @@ if (options.canUsePrivateInterfaceMethods()) { return; } - throw new ApiLevelException( - AndroidApiLevel.N, - "Private interface methods", - method.method.toSourceString()); + throw options.reporter.fatalError( + new PrivateInterfaceMethodDiagnostic(new MethodPosition(method.method))); } if (!method.accessFlags.isPublic()) { @@ -1383,10 +1381,7 @@ private void checkThatInvokeCustomIsAllowed() { if (!options.canUseInvokeCustom()) { - throw new ApiLevelException( - AndroidApiLevel.O, - "Invoke-customs", - null /* sourceString */); + throw options.reporter.fatalError(new InvokeCustomDiagnostic()); } } }
diff --git a/src/main/java/com/android/tools/r8/errors/ApiLevelDiagnostic.java b/src/main/java/com/android/tools/r8/errors/ApiLevelDiagnostic.java new file mode 100644 index 0000000..fde6860 --- /dev/null +++ b/src/main/java/com/android/tools/r8/errors/ApiLevelDiagnostic.java
@@ -0,0 +1,22 @@ +// 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; + +// TODO(b/154778581): Flesh out this class/interface and keep it. +public abstract class ApiLevelDiagnostic implements Diagnostic { + + @Override + public Origin getOrigin() { + return Origin.unknown(); + } + + @Override + public Position getPosition() { + return Position.UNKNOWN; + } +}
diff --git a/src/main/java/com/android/tools/r8/errors/ClassFileOverflowDiagnostic.java b/src/main/java/com/android/tools/r8/errors/ClassFileOverflowDiagnostic.java new file mode 100644 index 0000000..f9d49f0 --- /dev/null +++ b/src/main/java/com/android/tools/r8/errors/ClassFileOverflowDiagnostic.java
@@ -0,0 +1,29 @@ +// 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.Keep; +import com.android.tools.r8.origin.Origin; +import com.android.tools.r8.position.Position; + +@Keep +public abstract class ClassFileOverflowDiagnostic implements Diagnostic { + + private final Origin origin; + + public ClassFileOverflowDiagnostic(Origin origin) { + this.origin = origin; + } + + @Override + public Origin getOrigin() { + return origin; + } + + @Override + public Position getPosition() { + return Position.UNKNOWN; + } +}
diff --git a/src/main/java/com/android/tools/r8/errors/CodeSizeOverflowDiagnostic.java b/src/main/java/com/android/tools/r8/errors/CodeSizeOverflowDiagnostic.java new file mode 100644 index 0000000..5359ee0 --- /dev/null +++ b/src/main/java/com/android/tools/r8/errors/CodeSizeOverflowDiagnostic.java
@@ -0,0 +1,49 @@ +// 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.Keep; +import com.android.tools.r8.origin.Origin; +import com.android.tools.r8.position.MethodPosition; +import com.android.tools.r8.position.Position; +import com.android.tools.r8.references.MethodReference; + +/** + * Diagnostic information about a class file which could not be generated as the code size of a + * method overflowed the limit. + */ +@Keep +public class CodeSizeOverflowDiagnostic extends ClassFileOverflowDiagnostic { + + private final MethodReference method; + private final int codeSize; + private final MethodPosition position; + + public CodeSizeOverflowDiagnostic(Origin origin, MethodReference method, int codeSize) { + super(origin); + this.method = method; + this.codeSize = codeSize; + this.position = new MethodPosition(method); + } + + /** Code size of the method. */ + public int getCodeSize() { + return codeSize; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public String getDiagnosticMessage() { + return "Method " + + method + + " too large for class file." + + " Code size was " + + getCodeSize() + + "."; + } +}
diff --git a/src/main/java/com/android/tools/r8/errors/ConstantPoolOverflowDiagnostic.java b/src/main/java/com/android/tools/r8/errors/ConstantPoolOverflowDiagnostic.java new file mode 100644 index 0000000..3c39f22 --- /dev/null +++ b/src/main/java/com/android/tools/r8/errors/ConstantPoolOverflowDiagnostic.java
@@ -0,0 +1,40 @@ +// 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.Keep; +import com.android.tools.r8.origin.Origin; +import com.android.tools.r8.references.ClassReference; + +/** + * Diagnostic information about a class file which could not be generated as the size of the + * required constant pool overflowed the limit. + */ +@Keep +public class ConstantPoolOverflowDiagnostic extends ClassFileOverflowDiagnostic { + + private final int constantPoolSize; + private final ClassReference clazz; + + public ConstantPoolOverflowDiagnostic(Origin origin, ClassReference clazz, int constantPoolSize) { + super(origin); + this.clazz = clazz; + this.constantPoolSize = constantPoolSize; + } + + /** Constant pool size of the clazz. */ + public int getConstantPoolSize() { + return constantPoolSize; + } + + @Override + public String getDiagnosticMessage() { + return "Class " + + clazz + + " too large for class file." + + " Constant pool size was " + + getConstantPoolSize() + + "."; + } +}
diff --git a/src/main/java/com/android/tools/r8/errors/DefaultInterfaceMethodDiagnostic.java b/src/main/java/com/android/tools/r8/errors/DefaultInterfaceMethodDiagnostic.java new file mode 100644 index 0000000..b0dfe4e --- /dev/null +++ b/src/main/java/com/android/tools/r8/errors/DefaultInterfaceMethodDiagnostic.java
@@ -0,0 +1,30 @@ +// 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.ApiLevelException; +import com.android.tools.r8.position.MethodPosition; +import com.android.tools.r8.position.Position; +import com.android.tools.r8.utils.AndroidApiLevel; + +public class DefaultInterfaceMethodDiagnostic extends ApiLevelDiagnostic { + + private final MethodPosition position; + + public DefaultInterfaceMethodDiagnostic(MethodPosition position) { + assert position != null; + this.position = position; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public String getDiagnosticMessage() { + return ApiLevelException.makeMessage( + AndroidApiLevel.N, "Default interface methods", position.toString()); + } +}
diff --git a/src/main/java/com/android/tools/r8/errors/InvokeCustomDiagnostic.java b/src/main/java/com/android/tools/r8/errors/InvokeCustomDiagnostic.java new file mode 100644 index 0000000..ab8ff24 --- /dev/null +++ b/src/main/java/com/android/tools/r8/errors/InvokeCustomDiagnostic.java
@@ -0,0 +1,15 @@ +// 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.ApiLevelException; +import com.android.tools.r8.utils.AndroidApiLevel; + +public class InvokeCustomDiagnostic extends ApiLevelDiagnostic { + + @Override + public String getDiagnosticMessage() { + return ApiLevelException.makeMessage(AndroidApiLevel.O, "Invoke-customs", null); + } +}
diff --git a/src/main/java/com/android/tools/r8/errors/PrivateInterfaceMethodDiagnostic.java b/src/main/java/com/android/tools/r8/errors/PrivateInterfaceMethodDiagnostic.java new file mode 100644 index 0000000..568a7a0 --- /dev/null +++ b/src/main/java/com/android/tools/r8/errors/PrivateInterfaceMethodDiagnostic.java
@@ -0,0 +1,30 @@ +// 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.ApiLevelException; +import com.android.tools.r8.position.MethodPosition; +import com.android.tools.r8.position.Position; +import com.android.tools.r8.utils.AndroidApiLevel; + +public class PrivateInterfaceMethodDiagnostic extends ApiLevelDiagnostic { + + private final MethodPosition position; + + public PrivateInterfaceMethodDiagnostic(MethodPosition position) { + assert position != null; + this.position = position; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public String getDiagnosticMessage() { + return ApiLevelException.makeMessage( + AndroidApiLevel.N, "Private interface methods", position.toString()); + } +}
diff --git a/src/main/java/com/android/tools/r8/errors/StaticInterfaceMethodDiagnostic.java b/src/main/java/com/android/tools/r8/errors/StaticInterfaceMethodDiagnostic.java new file mode 100644 index 0000000..cb00b94 --- /dev/null +++ b/src/main/java/com/android/tools/r8/errors/StaticInterfaceMethodDiagnostic.java
@@ -0,0 +1,30 @@ +// 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.ApiLevelException; +import com.android.tools.r8.position.MethodPosition; +import com.android.tools.r8.position.Position; +import com.android.tools.r8.utils.AndroidApiLevel; + +public class StaticInterfaceMethodDiagnostic extends ApiLevelDiagnostic { + + private final MethodPosition position; + + public StaticInterfaceMethodDiagnostic(MethodPosition position) { + assert position != null; + this.position = position; + } + + @Override + public Position getPosition() { + return position; + } + + @Override + public String getDiagnosticMessage() { + return ApiLevelException.makeMessage( + AndroidApiLevel.N, "Static interface methods", position.toString()); + } +}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java index 6e99fbe..7071fda 100644 --- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java +++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -773,24 +773,24 @@ } public DexEncodedMethod toEmptyThrowingMethod(InternalOptions options) { - return options.isGeneratingClassFiles() - ? toEmptyThrowingMethodCf() - : toEmptyThrowingMethodDex(); - } - - public DexEncodedMethod toEmptyThrowingMethodDex() { - checkIfObsolete(); - assert !shouldNotHaveCode(); - Builder builder = builder(this); - builder.setCode(buildEmptyThrowingDexCode()); - if (isNonPrivateVirtualMethod()) { - builder.setIsLibraryMethodOverride(isLibraryMethodOverride()); - } // Note that we are not marking this instance obsolete, since this util is only used by // TreePruner while keeping non-live yet targeted, empty method. Such method can be retrieved // again only during the 2nd round of tree sharking, and seeing an obsolete empty body v.s. // seeing this empty throwing code do not matter. // If things are changed, the cure point is obsolete instances inside RootSet. + return options.isGeneratingClassFiles() + ? toEmptyThrowingMethodCf() + : toEmptyThrowingMethodDex(true); + } + + public DexEncodedMethod toEmptyThrowingMethodDex(boolean setIsLibraryOverride) { + checkIfObsolete(); + assert !shouldNotHaveCode(); + Builder builder = builder(this); + builder.setCode(buildEmptyThrowingDexCode()); + if (setIsLibraryOverride && isNonPrivateVirtualMethod()) { + builder.setIsLibraryMethodOverride(isLibraryMethodOverride()); + } return builder.build(); } @@ -805,7 +805,7 @@ Collections.emptyList()); } - public DexEncodedMethod toEmptyThrowingMethodCf() { + private DexEncodedMethod toEmptyThrowingMethodCf() { checkIfObsolete(); assert !shouldNotHaveCode(); Builder builder = builder(this);
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethod.java b/src/main/java/com/android/tools/r8/graph/DexMethod.java index 5236191..d3dd5fc 100644 --- a/src/main/java/com/android/tools/r8/graph/DexMethod.java +++ b/src/main/java/com/android/tools/r8/graph/DexMethod.java
@@ -33,15 +33,16 @@ return "Method " + holder + "." + name + " " + proto.toString(); } - public MethodReference asMethodReference(AppView<?> appView) { + public MethodReference asMethodReference() { List<TypeReference> parameters = new ArrayList<>(); for (DexType value : proto.parameters.values) { parameters.add(Reference.typeFromDescriptor(value.toDescriptorString())); } + String returnTypeDescriptor = proto.returnType.toDescriptorString(); TypeReference returnType = - proto.returnType == appView.dexItemFactory().voidType + returnTypeDescriptor.equals("V") ? null - : Reference.typeFromDescriptor(proto.returnType.toDescriptorString()); + : Reference.typeFromDescriptor(returnTypeDescriptor); return Reference.method( Reference.classFromDescriptor(holder.toDescriptorString()), name.toString(),
diff --git a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java index e7a799d..06f8c42 100644 --- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java +++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -375,7 +375,7 @@ throw new CompilationError( "Absent Code attribute in method that is not native or abstract", origin, - new MethodPosition(method)); + new MethodPosition(method.asMethodReference())); } code.setCode( new CfCode(
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java index f1a6b89..b79a063 100644 --- a/src/main/java/com/android/tools/r8/ir/code/Value.java +++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -64,7 +64,7 @@ + " by constraint: " + constraint, origin, - new MethodPosition(method))); + new MethodPosition(method.asMethodReference()))); } else if (constrainedType != type) { setType(constrainedType); }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java index ecd971f..dba65f7 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -1099,7 +1099,7 @@ MethodProcessingId methodProcessingId) { return ExceptionUtils.withOriginAndPositionAttachmentHandler( method.getOrigin(), - new MethodPosition(method.getReference()), + new MethodPosition(method.getReference().asMethodReference()), () -> rewriteCodeInternal(method, feedback, methodProcessor, methodProcessingId)); }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java b/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java index 8279864..4c073e1 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
@@ -152,7 +152,7 @@ + ", its imprecise type is: " + stillImprecise.get(0).getType(), code.origin, - new MethodPosition(code.method().method))); + new MethodPosition(code.method().method.asMethodReference()))); } }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java index b32ab3b..4737d39 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -386,7 +386,7 @@ "Attempt to add forwarding method that conflicts with existing method.", null, clazz.getOrigin(), - new MethodPosition(methodOnSelf.method)); + new MethodPosition(methodOnSelf.method.asMethodReference())); } DexMethod method = target.method;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java index 9d14d61..250737f 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
@@ -453,8 +453,7 @@ libraryClass.type, libraryClass.superType, message, - retarget, - appView); + retarget); } private DexType dispatchInterfaceTypeFor(DexMethod method) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java index 79a8a40..901517a 100644 --- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java +++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -1124,7 +1124,7 @@ } DexMethod method = appView.graphLense().getOriginalMethodSignature(referencedFrom); Origin origin = getMethodOrigin(method); - MethodPosition position = new MethodPosition(method); + MethodPosition position = new MethodPosition(method.asMethodReference()); options.warningMissingTypeForDesugar(origin, position, missing, method); }
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java index 4f1e59a..18de3c5 100644 --- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java +++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -11,6 +11,8 @@ import com.android.tools.r8.ClassFileConsumer; import com.android.tools.r8.dex.ApplicationWriter; import com.android.tools.r8.dex.Marker; +import com.android.tools.r8.errors.CodeSizeOverflowDiagnostic; +import com.android.tools.r8.errors.ConstantPoolOverflowDiagnostic; import com.android.tools.r8.errors.Unimplemented; import com.android.tools.r8.errors.Unreachable; import com.android.tools.r8.graph.AppView; @@ -36,6 +38,7 @@ import com.android.tools.r8.graph.ParameterAnnotationsList; import com.android.tools.r8.naming.NamingLens; import com.android.tools.r8.naming.ProguardMapSupplier; +import com.android.tools.r8.references.Reference; import com.android.tools.r8.utils.ExceptionUtils; import com.android.tools.r8.utils.InternalOptions; import com.google.common.collect.ImmutableMap; @@ -45,8 +48,10 @@ import java.util.Optional; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassTooLargeException; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodTooLargeException; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; @@ -109,7 +114,30 @@ if (clazz.getSynthesizedFrom().isEmpty() || options.isDesugaredLibraryCompilation() || options.cfToCfDesugar) { - writeClass(clazz, consumer, markerString); + try { + writeClass(clazz, consumer, markerString); + } catch (ClassTooLargeException e) { + throw appView + .options() + .reporter + .fatalError( + new ConstantPoolOverflowDiagnostic( + clazz.getOrigin(), + Reference.classFromBinaryName(e.getClassName()), + e.getConstantPoolCount())); + } catch (MethodTooLargeException e) { + throw appView + .options() + .reporter + .fatalError( + new CodeSizeOverflowDiagnostic( + clazz.getOrigin(), + Reference.methodFromDescriptor( + Reference.classFromBinaryName(e.getClassName()).getDescriptor(), + e.getMethodName(), + e.getDescriptor()), + e.getCodeSize())); + } } else { throw new Unimplemented("No support for synthetics in the Java bytecode backend."); }
diff --git a/src/main/java/com/android/tools/r8/position/MethodPosition.java b/src/main/java/com/android/tools/r8/position/MethodPosition.java index 3f22117..fa86ac8 100644 --- a/src/main/java/com/android/tools/r8/position/MethodPosition.java +++ b/src/main/java/com/android/tools/r8/position/MethodPosition.java
@@ -5,8 +5,8 @@ import com.android.tools.r8.Keep; import com.android.tools.r8.graph.DexMethod; -import com.android.tools.r8.graph.DexType; -import java.util.Arrays; +import com.android.tools.r8.references.MethodReference; +import com.android.tools.r8.references.TypeReference; import java.util.List; import java.util.stream.Collectors; @@ -14,38 +14,46 @@ @Keep public class MethodPosition implements Position { - // Do not expose the internal dex method structure. - private DexMethod method; + private final MethodReference method; + @Deprecated public MethodPosition(DexMethod method) { + this(method.asMethodReference()); + } + + public MethodPosition(MethodReference method) { this.method = method; } + /** The method */ + public MethodReference getMethod() { + return method; + } /** The unqualified name of the method. */ public String getName() { - return method.name.toString(); + return method.getMethodName(); } /** The type descriptor of the method holder. */ public String getHolder() { - return method.holder.toDescriptorString(); + return method.getHolderClass().getDescriptor(); } /** The type descriptor of the methods return type. */ public String getReturnType() { - return method.proto.returnType.toDescriptorString(); + return method.getReturnType().getDescriptor(); } /** The type descriptors for the methods formal parameter types. */ public List<String> getParameterTypes() { - return Arrays.stream(method.proto.parameters.values) - .map(DexType::toDescriptorString) + return method.getFormalTypes().stream() + .map(TypeReference::getDescriptor) .collect(Collectors.toList()); } @Override public String toString() { - return method.toSourceString(); + return method.toString(); } @Override
diff --git a/src/main/java/com/android/tools/r8/references/Reference.java b/src/main/java/com/android/tools/r8/references/Reference.java index 1071cbd..f2c5442 100644 --- a/src/main/java/com/android/tools/r8/references/Reference.java +++ b/src/main/java/com/android/tools/r8/references/Reference.java
@@ -181,6 +181,22 @@ return method(classFromClass(holderClass), "<init>", builder.build(), null); } + /** Get a method reference from class name, method name and signature. */ + public static MethodReference methodFromDescriptor( + String classDescriptor, String methodName, String methodDescriptor) { + ImmutableList.Builder<TypeReference> builder = ImmutableList.builder(); + for (String parameterTypeDescriptor : + DescriptorUtils.getArgumentTypeDescriptors(methodDescriptor)) { + builder.add(typeFromDescriptor(parameterTypeDescriptor)); + } + String returnTypeDescriptor = DescriptorUtils.getReturnTypeDescriptor(methodDescriptor); + return method( + classFromDescriptor(classDescriptor), + methodName, + builder.build(), + returnTypeDescriptor.equals("V") ? null : typeFromDescriptor(returnTypeDescriptor)); + } + public static MethodReference classConstructor(ClassReference type) { return method(type, "<clinit>", Collections.emptyList(), null); }
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 997d4e9..43a53c7 100644 --- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java +++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -75,7 +75,6 @@ import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Predicate; -import java.util.stream.Collectors; import org.objectweb.asm.Opcodes; public class InternalOptions { @@ -482,9 +481,6 @@ // to disable the check that the build makes sense for multi-dexing. public boolean enableMainDexListCheck = true; - // TODO(b/156934674): Remove when resource shrinker is removed. - public boolean isRunningDeprecatedResourceShrinker = false; - private final boolean enableTreeShaking; private final boolean enableMinification; @@ -875,8 +871,7 @@ DexType libraryType, DexType invalidSuperType, String message, - Set<DexMethod> retarget, - AppView<?> appView) { + Set<DexMethod> retarget) { if (invalidLibraryClasses.add(invalidSuperType)) { reporter.warning( new InvalidLibrarySuperclassDiagnostic( @@ -884,9 +879,7 @@ Reference.classFromDescriptor(libraryType.toDescriptorString()), Reference.classFromDescriptor(invalidSuperType.toDescriptorString()), message, - retarget.stream() - .map(method -> method.asMethodReference(appView)) - .collect(Collectors.toList()))); + ListUtils.map(retarget, DexMethod::asMethodReference))); } }
diff --git a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java index be6ffbb..8ae9c0f 100644 --- a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java +++ b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -242,8 +242,12 @@ return self(); } - public T setEnableDesugaring(boolean enableDesugaring) { - builder.setEnableDesugaring(enableDesugaring); + public T disableDesugaring() { + return setDisableDesugaring(true); + } + + public T setDisableDesugaring(boolean disableDesugaring) { + builder.setDisableDesugaring(disableDesugaring); return self(); }
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeStaticInvokeTest.java b/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeStaticInvokeTest.java index 7422eb8..2ee795b 100644 --- a/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeStaticInvokeTest.java +++ b/src/test/java/com/android/tools/r8/desugar/DesugarMissingTypeStaticInvokeTest.java
@@ -19,6 +19,7 @@ import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic; import com.android.tools.r8.references.Reference; import com.android.tools.r8.utils.AndroidApiLevel; +import com.android.tools.r8.utils.DescriptorUtils; import com.android.tools.r8.utils.StringUtils; import org.junit.Test; import org.junit.runner.RunWith; @@ -80,7 +81,9 @@ assertEquals(Reference.classFromClass(TestClass.class), desugarWarning.getContextType()); assertThat( desugarWarning.getPosition().getDescription(), - containsString(TestClass.class.getTypeName() + ".main")); + containsString( + DescriptorUtils.javaTypeToDescriptor(TestClass.class.getTypeName()) + + "main([Ljava/lang/String;)V")); } } }
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFile.java b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFile.java index e8ac332..39f0ef1 100644 --- a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFile.java +++ b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFile.java
@@ -65,7 +65,7 @@ testForD8() .addProgramFiles(jar) .setMinApi(parameters.getApiLevel()) - .setEnableDesugaring(false) + .disableDesugaring() .run(parameters.getRuntime(), TestClass.class) .assertSuccessWithOutputLines("Hello, world!", "I::foo"); }
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileInputCfVersion.java b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileInputCfVersion.java index 0fd267d..49437ff 100644 --- a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileInputCfVersion.java +++ b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileInputCfVersion.java
@@ -68,7 +68,7 @@ testForD8() .addProgramFiles(jar) .setMinApi(parameters.getApiLevel()) - .setEnableDesugaring(false) + .disableDesugaring() .run(parameters.getRuntime(), TestClass.class) .assertSuccessWithOutputLines("Hello, world!"); }
diff --git a/src/test/java/com/android/tools/r8/diagnostics/ApiLevelDiagnosticTest.java b/src/test/java/com/android/tools/r8/diagnostics/ApiLevelDiagnosticTest.java new file mode 100644 index 0000000..40fab17 --- /dev/null +++ b/src/test/java/com/android/tools/r8/diagnostics/ApiLevelDiagnosticTest.java
@@ -0,0 +1,124 @@ +// 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.diagnostics; + +import static com.android.tools.r8.DiagnosticsMatcher.diagnosticMessage; +import static org.hamcrest.CoreMatchers.startsWith; + +import com.android.tools.r8.CompilationFailedException; +import com.android.tools.r8.TestBase; +import com.android.tools.r8.TestParameters; +import com.android.tools.r8.TestParametersCollection; +import com.android.tools.r8.utils.AndroidApiLevel; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +// TODO(b/154778581): Extend these tests with typed diagnostics and improved information. +@RunWith(Parameterized.class) +public class ApiLevelDiagnosticTest extends TestBase { + + // Hard coded messages in AGP. See D8DexArchiveBuilder. + + private static final String AGP_INVOKE_CUSTOM = + "Invoke-customs are only supported starting with Android O"; + + private static final String AGP_DEFAULT_INTERFACE_METHOD = + "Default interface methods are only supported starting with Android N (--min-api 24)"; + + private static final String AGP_STATIC_INTERFACE_METHOD = + "Static interface methods are only supported starting with Android N (--min-api 24)"; + + @Parameterized.Parameters(name = "{0}") + public static TestParametersCollection data() { + return getTestParameters().withNoneRuntime().build(); + } + + public ApiLevelDiagnosticTest(TestParameters parameters) {} + + @Test(expected = CompilationFailedException.class) + public void testInvokeLambdaMetafactory() throws Exception { + testForD8() + .addProgramClassesAndInnerClasses(LambdaMetafactoryTest.class) + .setMinApi(AndroidApiLevel.B) + .disableDesugaring() + .compileWithExpectedDiagnostics( + diagnostics -> { + diagnostics + .assertOnlyErrors() + .assertErrorsMatch(diagnosticMessage(startsWith(AGP_INVOKE_CUSTOM))); + }); + } + + @Test(expected = CompilationFailedException.class) + public void testDefaultInterfaceMethods() throws Exception { + testForD8() + .addProgramClassesAndInnerClasses(DefaultInterfaceMethodsTest.class) + .setMinApi(AndroidApiLevel.B) + .disableDesugaring() + .compileWithExpectedDiagnostics( + diagnostics -> { + diagnostics + .assertOnlyErrors() + .assertErrorsMatch(diagnosticMessage(startsWith(AGP_DEFAULT_INTERFACE_METHOD))); + }); + } + + @Test(expected = CompilationFailedException.class) + public void testStaticInterfaceMethods() throws Exception { + testForD8() + .addProgramClassesAndInnerClasses(StaticInterfaceMethodsTest.class) + .setMinApi(AndroidApiLevel.B) + .disableDesugaring() + .compileWithExpectedDiagnostics( + diagnostics -> { + diagnostics + .assertOnlyErrors() + .assertErrorsMatch(diagnosticMessage(startsWith(AGP_STATIC_INTERFACE_METHOD))); + }); + } + + static class LambdaMetafactoryTest { + + public interface StringSupplier { + String get(); + } + + public static void print(StringSupplier supplier) { + System.out.println(supplier.get()); + } + + public static void main(String[] args) { + print(() -> "Hello, world"); + } + } + + static class DefaultInterfaceMethodsTest { + + interface WithDefaults { + default void foo() { + System.out.println("WithDefaults::foo"); + } + } + + static class MyClass implements WithDefaults {} + + public static void main(String[] args) { + new MyClass().foo(); + } + } + + static class StaticInterfaceMethodsTest { + + interface WithStatics { + static void foo() { + System.out.println("WithStatics::foo"); + } + } + + public static void main(String[] args) { + WithStatics.foo(); + } + } +}