Merge "Update Proguard 6.0 to Proguard 6.0.1"
diff --git a/build.gradle b/build.gradle
index 6a821a5..716f983 100644
--- a/build.gradle
+++ b/build.gradle
@@ -36,7 +36,7 @@
joptSimpleVersion = '4.6'
jsonSimpleVersion = '1.1'
junitVersion = '4.12'
- kotlinVersion = '1.2.0'
+ kotlinVersion = '1.2.30'
protobufVersion = '3.0.0'
smaliVersion = '2.2b4'
}
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 670211f..9404e68 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "v1.1.9-dev";
+ public static final String LABEL = "v1.1.10-dev";
private Version() {
}
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 42acb7c..d6b15eb 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -146,6 +146,46 @@
return result;
}
+ /**
+ * For all annotations on the class and all annotations on its methods and fields apply the
+ * specified consumer.
+ */
+ public void forEachAnnotation(Consumer<DexAnnotation> consumer) {
+ for (DexAnnotation annotation : annotations.annotations) {
+ consumer.accept(annotation);
+ }
+ for (DexEncodedMethod method : directMethods()) {
+ for (DexAnnotation annotation : method.annotations.annotations) {
+ consumer.accept(annotation);
+ }
+ for (DexAnnotationSet parameterAnnotations : method.parameterAnnotations.values) {
+ for (DexAnnotation annotation : parameterAnnotations.annotations) {
+ consumer.accept(annotation);
+ }
+ }
+ }
+ for (DexEncodedMethod method : virtualMethods()) {
+ for (DexAnnotation annotation : method.annotations.annotations) {
+ consumer.accept(annotation);
+ }
+ for (DexAnnotationSet parameterAnnotations : method.parameterAnnotations.values) {
+ for (DexAnnotation annotation : parameterAnnotations.annotations) {
+ consumer.accept(annotation);
+ }
+ }
+ }
+ for (DexEncodedField field : instanceFields()) {
+ for (DexAnnotation annotation : field.annotations.annotations) {
+ consumer.accept(annotation);
+ }
+ }
+ for (DexEncodedField field : staticFields()) {
+ for (DexAnnotation annotation : field.annotations.annotations) {
+ consumer.accept(annotation);
+ }
+ }
+ }
+
public void forEachField(Consumer<DexEncodedField> consumer) {
for (DexEncodedField field : staticFields()) {
consumer.accept(field);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 76a1a43..20051f9 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -396,10 +396,6 @@
// necessary.
ir.splitCriticalEdges();
- // Create block order and make sure that all blocks are immediately followed by their
- // fallthrough block if any.
- ir.traceBlocks();
-
// Clear the code so we don't build multiple times.
source.clear();
source = null;
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 42b06ef..0f0b44a 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
@@ -476,6 +476,7 @@
Log.debug(getClass(), "Initial (SSA) flow graph for %s:\n%s", method.toSourceString(), code);
}
assert code.isConsistentSSA();
+ code.traceBlocks();
RegisterAllocator registerAllocator = performRegisterAllocation(code, method);
method.setCode(code, registerAllocator, options);
if (Log.ENABLED) {
@@ -635,7 +636,6 @@
if (options.testing.invertConditionals) {
invertConditionalsForTesting(code);
- code.traceBlocks();
}
if (options.enableNonNullTracking && nonNullTracker != null) {
@@ -699,6 +699,7 @@
}
private void finalizeIR(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
+ code.traceBlocks();
if (options.isGeneratingClassFiles()) {
finalizeToCf(method, code, feedback);
} else {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index a6b29e8..30e9bae4 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -565,7 +565,6 @@
// being split on the way in but does not maintain this property. We therefore split
// critical edges at exit.
code.splitCriticalEdges();
- code.traceBlocks();
assert code.isConsistentSSA();
}
@@ -2028,9 +2027,6 @@
}
code.removeMarkedBlocks(color);
code.returnMarkingColor(color);
- if (ifBranchFlipped) {
- code.traceBlocks();
- }
assert code.isConsistentSSA();
}
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index acf4395..85e0060 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -54,6 +54,8 @@
import java.util.PriorityQueue;
import java.util.Set;
import java.util.TreeSet;
+import java.util.function.BiPredicate;
+import java.util.function.Predicate;
/**
* Linear scan register allocator.
@@ -1348,10 +1350,17 @@
// free position.
int candidate = getLargestValidCandidate(
unhandledInterval, registerConstraint, needsRegisterPair, freePositions, Type.ANY);
- assert candidate != REGISTER_CANDIDATE_NOT_FOUND;
- int largestFreePosition = freePositions.get(candidate);
- if (needsRegisterPair) {
- largestFreePosition = Math.min(largestFreePosition, freePositions.get(candidate + 1));
+
+ // It is not always possible to find a largest valid candidate. If none of the usable register
+ // are free we typically get the last candidate. However, if that candidate has to be
+ // discarded in order to workaround bugs we get REGISTER_CANDIDATE_NOT_FOUND. In both cases
+ // we need to spill a valid candidate. That path is triggered when largestFreePosition is 0.
+ int largestFreePosition = 0;
+ if (candidate != REGISTER_CANDIDATE_NOT_FOUND) {
+ largestFreePosition = freePositions.get(candidate);
+ if (needsRegisterPair) {
+ largestFreePosition = Math.min(largestFreePosition, freePositions.get(candidate + 1));
+ }
}
// Determine what to do based on how long the selected candidate is free.
@@ -1554,57 +1563,47 @@
return candidate;
}
+ private int handleWorkaround(
+ Predicate<LiveIntervals> workaroundNeeded,
+ BiPredicate<LiveIntervals, Integer> workaroundNeededForCandidate,
+ int candidate, LiveIntervals unhandledInterval, int registerConstraint,
+ boolean needsRegisterPair, RegisterPositions freePositions, RegisterPositions.Type type) {
+ if (workaroundNeeded.test(unhandledInterval)) {
+ int lastCandidate = candidate;
+ while (workaroundNeededForCandidate.test(unhandledInterval, candidate)) {
+ // Make the unusable register unavailable for allocation and try again.
+ freePositions.set(candidate, 0);
+ candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, type);
+ // If there are only invalid candidates of the give type we will end up with the same
+ // candidate returned again once we have tried them all. In that case we didn't find a
+ // valid register candidate and we need to broaden the search to other types.
+ if (lastCandidate == candidate) {
+ return REGISTER_CANDIDATE_NOT_FOUND;
+ }
+ lastCandidate = candidate;
+ }
+ }
+ return candidate;
+ }
+
private int getLargestValidCandidate(LiveIntervals unhandledInterval, int registerConstraint,
boolean needsRegisterPair, RegisterPositions freePositions, RegisterPositions.Type type) {
int candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, type);
if (candidate == REGISTER_CANDIDATE_NOT_FOUND) {
return candidate;
}
- if (needsLongResultOverlappingLongOperandsWorkaround(unhandledInterval)) {
- int lastCandidate = candidate;
- while (isLongResultOverlappingLongOperands(unhandledInterval, candidate)) {
- // Make the overlapping register unavailable for allocation and try again.
- freePositions.set(candidate, 0);
- candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, type);
- // If there are only invalid candidates of the give type we will end up with the same
- // candidate returned again once we have tried them all. In that case we didn't find a
- // valid register candidate and we need to broaden the search to other types.
- if (lastCandidate == candidate) {
- return REGISTER_CANDIDATE_NOT_FOUND;
- }
- lastCandidate = candidate;
- }
- }
- if (needsSingleResultOverlappingLongOperandsWorkaround(unhandledInterval)) {
- int lastCandidate = candidate;
- while (isSingleResultOverlappingLongOperands(unhandledInterval, candidate)) {
- // Make the overlapping register unavailable for allocation and try again.
- freePositions.set(candidate, 0);
- candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, type);
- // If there are only invalid candidates of the give type we will end up with the same
- // candidate returned again once we have tried them all. In that case we didn't find a
- // valid register candidate and we need to broaden the search to other types.
- if (lastCandidate == candidate) {
- return REGISTER_CANDIDATE_NOT_FOUND;
- }
- lastCandidate = candidate;
- }
- }
- if (needsArrayGetWideWorkaround(unhandledInterval)) {
- int lastCandidate = candidate;
- while (isArrayGetArrayRegister(unhandledInterval, candidate)) {
- // Make the overlapping register unavailable for allocation and try again.
- freePositions.set(candidate, 0);
- candidate = getLargestCandidate(registerConstraint, freePositions, needsRegisterPair, type);
- // If there are only invalid candidates of the give type we will end up with the same
- // candidate returned again once we have tried them all. In that case we didn't find a
- // valid register candidate and we need to broaden the search to other types.
- if (lastCandidate == candidate) {
- return REGISTER_CANDIDATE_NOT_FOUND;
- }
- lastCandidate = candidate;
- }
- }
+ candidate = handleWorkaround(
+ this::needsLongResultOverlappingLongOperandsWorkaround,
+ this::isLongResultOverlappingLongOperands,
+ candidate, unhandledInterval, registerConstraint, needsRegisterPair, freePositions, type);
+ candidate = handleWorkaround(
+ this::needsSingleResultOverlappingLongOperandsWorkaround,
+ this::isSingleResultOverlappingLongOperands,
+ candidate, unhandledInterval, registerConstraint, needsRegisterPair, freePositions, type);
+ candidate = handleWorkaround(
+ this::needsArrayGetWideWorkaround,
+ this::isArrayGetArrayRegister,
+ candidate, unhandledInterval, registerConstraint, needsRegisterPair, freePositions, type);
return candidate;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
index de21187..5c51786 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
@@ -85,13 +85,13 @@
addMainDexType(dexType);
continue;
}
- for (DexAnnotation annotation : clazz.annotations.annotations) {
- if (annotation.visibility == DexAnnotation.VISIBILITY_RUNTIME
+ clazz.forEachAnnotation(annotation -> {
+ if (!mainDexTypes.contains(dexType)
+ && annotation.visibility == DexAnnotation.VISIBILITY_RUNTIME
&& isAnnotationWithEnum(annotation.annotation.type)) {
addMainDexType(dexType);
- break;
}
- }
+ });
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
index b526973..e96de6f 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationParser.java
@@ -535,7 +535,7 @@
private ProguardIfRule parseIfRule(TextPosition optionStart)
throws ProguardRuleParserException {
ProguardIfRule.Builder ifRuleBuilder = ProguardIfRule.builder();
- parseClassSpec(ifRuleBuilder, true);
+ parseClassSpec(ifRuleBuilder, false);
// Required a subsequent keep rule.
skipWhitespace();
@@ -1086,15 +1086,52 @@
return Integer.parseInt(s);
}
+ private final Predicate<Character> CLASS_NAME_PREDICATE =
+ character -> IdentifierUtils.isDexIdentifierPart(character)
+ || character == '.'
+ || character == '*'
+ || character == '?'
+ || character == '%'
+ || character == '['
+ || character == ']';
+
private String acceptClassName() {
- return acceptString(character ->
- IdentifierUtils.isDexIdentifierPart(character)
- || character == '.'
- || character == '*'
- || character == '?'
- || character == '%'
- || character == '['
- || character == ']');
+ return acceptString(CLASS_NAME_PREDICATE);
+ }
+
+ private String acceptClassNameWithNthWildcard() {
+ StringBuilder nthWildcard = null;
+ skipWhitespace();
+ int start = position;
+ int end = position;
+ while (!eof(end)) {
+ char current = contents.charAt(end);
+ if (nthWildcard != null) {
+ if (current == '>') {
+ try {
+ Integer.parseUnsignedInt(nthWildcard.toString());
+ } catch (NullPointerException | NumberFormatException e) {
+ return null;
+ }
+ nthWildcard = null;
+ } else {
+ nthWildcard.append(current);
+ }
+ end++;
+ } else if (CLASS_NAME_PREDICATE.test(current)) {
+ end++;
+ } else if (current == '<') {
+ nthWildcard = new StringBuilder();
+ end++;
+ } else {
+ break;
+ }
+ }
+ if (start == end) {
+ return null;
+ }
+ position = end;
+ return contents.substring(start, end);
}
private String acceptFieldNameOrIntegerForReturn() {
@@ -1194,7 +1231,7 @@
}
private String parseClassName() throws ProguardRuleParserException {
- String name = acceptClassName();
+ String name = acceptClassNameWithNthWildcard();
if (name == null) {
throw parseError("Class name expected");
}
diff --git a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
index 46669ec..c37102c 100644
--- a/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/protolite/ProtoLitePruner.java
@@ -348,7 +348,6 @@
// the fallthrough label. This can introduce critical edges. Therefore, we split critical
// edges to maintain our edge-split form.
code.splitCriticalEdges();
- code.traceBlocks();
assert code.isConsistentSSA();
}
diff --git a/src/test/examples/multidex002/AnnotatedDirectMethod.java b/src/test/examples/multidex002/AnnotatedDirectMethod.java
new file mode 100644
index 0000000..761ea9a
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedDirectMethod.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2017, 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 multidex002;
+
+public class AnnotatedDirectMethod {
+
+ @AnnotationWithEnum3(AnnotationWithEnum3.Value3.VAL3_2)
+ private void foo() {
+ }
+}
diff --git a/src/test/examples/multidex002/AnnotatedInstanceField.java b/src/test/examples/multidex002/AnnotatedInstanceField.java
new file mode 100644
index 0000000..0209f44
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedInstanceField.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2017, 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 multidex002;
+
+public class AnnotatedInstanceField {
+
+ @AnnotationWithEnum3(AnnotationWithEnum3.Value3.VAL3_2)
+ public String value = "myValue";
+}
diff --git a/src/test/examples/multidex002/AnnotatedMethodParameter.java b/src/test/examples/multidex002/AnnotatedMethodParameter.java
new file mode 100644
index 0000000..49a9e6d
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedMethodParameter.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2017, 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 multidex002;
+
+public class AnnotatedMethodParameter {
+
+ public void foo(@AnnotationWithEnum3(AnnotationWithEnum3.Value3.VAL3_2) String val) {
+ }
+}
diff --git a/src/test/examples/multidex002/AnnotatedNotKept.java b/src/test/examples/multidex002/AnnotatedNotKept.java
new file mode 100644
index 0000000..500e7f0
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedNotKept.java
@@ -0,0 +1,10 @@
+// Copyright (c) 2017, 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 multidex002;
+
+@AnnotationWithoutEnum
+public class AnnotatedNotKept {
+
+}
diff --git a/src/test/examples/multidex002/AnnotatedStaticField.java b/src/test/examples/multidex002/AnnotatedStaticField.java
new file mode 100644
index 0000000..385d1d9
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedStaticField.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2017, 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 multidex002;
+
+public class AnnotatedStaticField {
+ @AnnotationWithEnum3(AnnotationWithEnum3.Value3.VAL3_2) public static String sValue = "myValue";
+}
diff --git a/src/test/examples/multidex002/AnnotatedVirtualMethod.java b/src/test/examples/multidex002/AnnotatedVirtualMethod.java
new file mode 100644
index 0000000..569bf84
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotatedVirtualMethod.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, 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 multidex002;
+
+public class AnnotatedVirtualMethod {
+
+ @AnnotationWithEnum3(AnnotationWithEnum3.Value3.VAL3_2)
+ public void foo() {
+
+ }
+}
diff --git a/src/test/examples/multidex002/AnnotationWithEnum3.java b/src/test/examples/multidex002/AnnotationWithEnum3.java
new file mode 100644
index 0000000..a8f8344
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotationWithEnum3.java
@@ -0,0 +1,19 @@
+// Copyright (c) 2017, 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 multidex002;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AnnotationWithEnum3 {
+
+ enum Value3 {
+ VAL3_1,
+ VAL3_2,
+ }
+
+ Value3 value();
+}
diff --git a/src/test/examples/multidex002/AnnotationWithoutEnum.java b/src/test/examples/multidex002/AnnotationWithoutEnum.java
new file mode 100644
index 0000000..5244971
--- /dev/null
+++ b/src/test/examples/multidex002/AnnotationWithoutEnum.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, 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 multidex002;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AnnotationWithoutEnum {
+
+}
diff --git a/src/test/examples/multidex002/ref-list-1.txt b/src/test/examples/multidex002/ref-list-1.txt
index 26dae34..922d417 100644
--- a/src/test/examples/multidex002/ref-list-1.txt
+++ b/src/test/examples/multidex002/ref-list-1.txt
@@ -1,8 +1,15 @@
Lmultidex002/Annotated2;
Lmultidex002/Annotated;
+Lmultidex002/AnnotatedDirectMethod;
+Lmultidex002/AnnotatedInstanceField;
+Lmultidex002/AnnotatedMethodParameter;
+Lmultidex002/AnnotatedStaticField;
+Lmultidex002/AnnotatedVirtualMethod;
Lmultidex002/AnnotationWithClass;
Lmultidex002/AnnotationWithEnum2;
+Lmultidex002/AnnotationWithEnum3;
Lmultidex002/AnnotationWithEnum;
+Lmultidex002/AnnotationWithoutEnum;
Lmultidex002/InterfaceWithEnum;
Lmultidex002/IntermediateClass;
Lmultidex002/MainActivity;
diff --git a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
index 8ff72c7..c4351ce 100644
--- a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
+++ b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
@@ -4542,7 +4542,7 @@
// java.lang.AssertionError: Failed to load serialization resource file: serialization/com/google/jctf/test/lib/java/util/concurrent/PriorityBlockingQueue/serialization/PriorityBlockingQueue_serialization_A01.golden.0.ser
.put("lang.ThreadGroup.destroy.ThreadGroup_destroy_A01",
- match(D8_COMPILER, runtimesUpTo(Version.V6_0_1)))
+ match(runtimesUpTo(Version.V6_0_1)))
// 1) t02
// java.lang.IllegalThreadStateException: Thread group still contains threads: Test group
// 2) t04
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index bf409d8..32c0175 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -145,10 +145,6 @@
.put("974-verify-interface-super", AndroidApiLevel.N)
// Desugaring of interface private methods is not yet supported.
.put("975-iface-private", AndroidApiLevel.N)
- // The extended check for overlapping long registers cause this to run out of registers.
- .put("421-large-frame", AndroidApiLevel.N)
- // The extended check for overlapping long registers cause this to run out of registers.
- .put("551-checker-shifter-operand", AndroidApiLevel.N)
.build();
// Tests that timeout when run with Art.
diff --git a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
index 5f6a5cc..84f6a08 100644
--- a/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ProguardConfigurationParserTest.java
@@ -37,6 +37,7 @@
import java.util.Collections;
import java.util.List;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
public class ProguardConfigurationParserTest extends TestBase {
@@ -544,7 +545,7 @@
assertTrue(
config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
assertTrue(
- config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
+ config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobar;")));
assertTrue(
config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
}
@@ -561,12 +562,47 @@
assertTrue(
config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
assertTrue(
- config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobaz;")));
+ config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboobar;")));
assertTrue(
config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
}
@Test
+ public void testAdaptClassStringsNthWildcard() throws Exception {
+ DexItemFactory dexItemFactory = new DexItemFactory();
+ ProguardConfigurationParser parser =
+ new ProguardConfigurationParser(dexItemFactory, reporter);
+ String wildcard = "-adaptclassstrings *foo<1>";
+ parser.parse(createConfigurationForTesting(ImmutableList.of(wildcard)));
+ verifyParserEndsCleanly();
+ ProguardConfiguration config = parser.getConfig();
+ assertFalse(
+ config.getAdaptClassStrings().matches(dexItemFactory.createType("Lfoobar;")));
+ assertFalse(
+ config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboofoobar;")));
+ // TODO(b/73800755): Use <n> while matching class name list.
+ //assertTrue(
+ // config.getAdaptClassStrings().matches(dexItemFactory.createType("Lboofooboo;")));
+ }
+
+ @Ignore("b/73800755: verify the range of <n>")
+ @Test
+ public void testAdaptClassStringsNthWildcard_outOfRange() throws Exception {
+ Path proguardConfig = writeTextToTempFile(
+ "-adaptclassstrings *foo<2>"
+ );
+ try {
+ ProguardConfigurationParser parser =
+ new ProguardConfigurationParser(new DexItemFactory(), reporter);
+ parser.parse(proguardConfig);
+ fail();
+ } catch (AbortException e) {
+ checkDiagnostic(handler.errors, proguardConfig, 1, 1,
+ "wildcard", "out", "range");
+ }
+ }
+
+ @Test
public void testIdentifierNameString() throws Exception {
ProguardConfigurationParser parser =
new ProguardConfigurationParser(new DexItemFactory(), reporter);
@@ -1173,6 +1209,43 @@
}
@Test
+ public void parse_if_nthWildcard() throws Exception {
+ Path proguardConfig = writeTextToTempFile(
+ "-if class **$R**",
+ "-keep class **$D<2>" // <2> corresponds to the 2nd ** in -if rule.
+ );
+ ProguardConfigurationParser parser =
+ new ProguardConfigurationParser(new DexItemFactory(), reporter);
+ parser.parse(proguardConfig);
+ checkDiagnostic(handler.warnings, proguardConfig, 1, 1,
+ "Ignoring", "-if");
+ ProguardConfiguration config = parser.getConfig();
+ assertEquals(1, config.getRules().size());
+ ProguardIfRule if0 = (ProguardIfRule) config.getRules().get(0);
+ assertEquals("**$R**", if0.getClassNames().toString());
+ assertEquals(ProguardKeepRuleType.KEEP, if0.subsequentRule.getType());
+ assertEquals("**$D<2>", if0.subsequentRule.getClassNames().toString());
+ }
+
+ @Ignore("b/73800755: verify the range of <n>")
+ @Test
+ public void parse_if_nthWildcard_outOfRange() throws Exception {
+ Path proguardConfig = writeTextToTempFile(
+ "-if class **$R**",
+ "-keep class **D<4>" // There are 3 ** in this rule.
+ );
+ try {
+ ProguardConfigurationParser parser =
+ new ProguardConfigurationParser(new DexItemFactory(), reporter);
+ parser.parse(proguardConfig);
+ fail();
+ } catch (AbortException e) {
+ checkDiagnostic(handler.errors, proguardConfig, 1, 1,
+ "wildcard", "out", "range");
+ }
+ }
+
+ @Test
public void parse_if_if() throws Exception {
Path proguardConfig = writeTextToTempFile(
"-if class **$$ModuleAdapter",
diff --git a/third_party/kotlin.tar.gz.sha1 b/third_party/kotlin.tar.gz.sha1
index e55712d..40f26fa 100644
--- a/third_party/kotlin.tar.gz.sha1
+++ b/third_party/kotlin.tar.gz.sha1
@@ -1 +1 @@
-6dc49791e5fcf4318ae5246eacc73718180508ce
\ No newline at end of file
+4b18d827485f53990ad47b81db2a025abaa325d1
\ No newline at end of file