Try to substitute constructor chains for IPUTs.

Match a constructor chain where each constructor either
forwards some or all of its arguments to the next (i.e.
superclass constructor or a constructor in the same class)
and may pass extra zeros (of any type, including null),
followed by any number of IPUTs on "this", storing either
arguments or zeros, until we reach the contructor of
java.lang.Object.

When collecting IPUTs from the constructor chain, remove
any IPUTs that store the same field as an IPUT that comes
later. This is safe in this case even if those IPUTs store
volatile fields because the uninitialized object reference
wasn't allowed to escape yet. Also remove any IPUTs that
store zero values as the allocated object is already zero
initialized.

Change-Id: If93022310bf04fe38ee741665ac4a65d4c2bb25f
diff --git a/test/569-checker-pattern-replacement/src-multidex/Base.java b/test/569-checker-pattern-replacement/src-multidex/Base.java
new file mode 100644
index 0000000..f4d59af
--- /dev/null
+++ b/test/569-checker-pattern-replacement/src-multidex/Base.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Base {
+  Base() {
+    intField = 0;               // Unnecessary IPUT.
+    doubleField = 0.0;          // Unnecessary IPUT.
+    objectField = null;         // Unnecessary IPUT.
+  }
+
+  Base(int intValue) {
+    intField = intValue;
+  }
+
+  Base(String stringValue) {
+    objectField = stringValue;  // Unnecessary IPUT.
+    stringField = stringValue;
+    objectField = null;         // Unnecessary IPUT.
+  }
+
+  Base(double doubleValue, Object objectValue) {
+    doubleField = doubleValue;
+    objectField = objectValue;
+  }
+
+  Base(int intValue, double doubleValue, Object objectValue) {
+    intField = intValue;
+    doubleField = doubleValue;
+    objectField = objectValue;
+  }
+
+  Base(int intValue, double doubleValue, Object objectValue, String stringValue) {
+    // Outside our limit of 3 IPUTs.
+    intField = intValue;
+    doubleField = doubleValue;
+    objectField = objectValue;
+    stringField = stringValue;
+  }
+
+  Base(double doubleValue) {
+    this(doubleValue, null);
+  }
+
+  Base(Object objectValue) {
+    // Unsupported forwarding of a value after a zero.
+    this(0.0, objectValue);
+  }
+
+  Base(int intValue, long dummy) {
+    this(intValue, 0.0, null);
+  }
+
+  public int intField;
+  public double doubleField;
+  public Object objectField;
+  public String stringField;
+}
diff --git a/test/569-checker-pattern-replacement/src-multidex/BaseWithFinalField.java b/test/569-checker-pattern-replacement/src-multidex/BaseWithFinalField.java
new file mode 100644
index 0000000..7a1d591
--- /dev/null
+++ b/test/569-checker-pattern-replacement/src-multidex/BaseWithFinalField.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class BaseWithFinalField {
+  BaseWithFinalField() {
+    intField = 0;
+  }
+
+  BaseWithFinalField(int intValue) {
+    intField = intValue;
+  }
+
+  public final int intField;
+}
diff --git a/test/569-checker-pattern-replacement/src-multidex/Derived.java b/test/569-checker-pattern-replacement/src-multidex/Derived.java
new file mode 100644
index 0000000..184563f
--- /dev/null
+++ b/test/569-checker-pattern-replacement/src-multidex/Derived.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public final class Derived extends Base {
+  public Derived() {
+    this(0);
+  }
+
+  public Derived(int intValue) {
+    super(intValue);
+  }
+
+  public Derived(String stringValue) {
+    super(stringValue);
+    stringField = null;   // Clear field set by Base.<init>(String).
+  }
+
+  public Derived(double doubleValue) {
+    super(doubleValue, null);
+  }
+
+  public Derived(int intValue, double doubleValue, Object objectValue) {
+    super(intValue, doubleValue, objectValue);
+    objectField = null;   // Clear field set by Base.<init>(int, double, Object).
+    intField = 0;         // Clear field set by Base.<init>(int, double, Object).
+  }
+
+  Derived(int intValue, double doubleValue, Object objectValue, String stringValue) {
+    super(intValue, doubleValue, objectValue, stringValue);
+    // Clearing fields here doesn't help because the superclass constructor must
+    // satisfy the pattern constraints on its own and it doesn't (it has 4 IPUTs).
+    intField = 0;
+    doubleField = 0.0;
+    objectField = null;
+    stringField = null;
+  }
+
+  public Derived(float floatValue) {
+    super();
+    floatField = floatValue;
+  }
+
+  public Derived(int intValue, double doubleValue, Object objectValue, float floatValue) {
+    super(intValue, doubleValue, objectValue);
+    objectField = null;   // Clear field set by Base.<init>(int, double, Object).
+    floatField = floatValue;
+  }
+
+  public float floatField;
+}
diff --git a/test/569-checker-pattern-replacement/src-multidex/DerivedInSecondDex.java b/test/569-checker-pattern-replacement/src-multidex/DerivedInSecondDex.java
new file mode 100644
index 0000000..50266e8
--- /dev/null
+++ b/test/569-checker-pattern-replacement/src-multidex/DerivedInSecondDex.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public final class DerivedInSecondDex extends BaseInMainDex {
+  DerivedInSecondDex() {
+    super();
+  }
+
+  DerivedInSecondDex(int intValue) {
+    // Not matched: Superclass in a different dex file has an IPUT.
+    super(intValue);
+  }
+
+  DerivedInSecondDex(long dummy) {
+    // Matched: Superclass in a different dex file has an IPUT that's pruned because we store 0.
+    super(0);
+  }
+}
diff --git a/test/569-checker-pattern-replacement/src-multidex/DerivedWithFinalField.java b/test/569-checker-pattern-replacement/src-multidex/DerivedWithFinalField.java
new file mode 100644
index 0000000..5b39b8a
--- /dev/null
+++ b/test/569-checker-pattern-replacement/src-multidex/DerivedWithFinalField.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public final class DerivedWithFinalField extends BaseWithFinalField {
+  DerivedWithFinalField() {
+    this(0);
+  }
+
+  DerivedWithFinalField(int intValue) {
+    super(intValue);
+    doubleField = 0.0;
+  }
+
+  DerivedWithFinalField(double doubleValue) {
+    super(0);
+    doubleField = doubleValue;
+  }
+
+  DerivedWithFinalField(int intValue, double doubleValue) {
+    super(intValue);
+    doubleField = doubleValue;
+  }
+
+  public final double doubleField;
+}