Fix side effect model for StringBuilder.<init>(CharSequence)

Change-Id: Idbc492d7b0aab4813d9e9aefafa814f52b45db33
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 8f46be4..a93000e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -1628,9 +1628,10 @@
     public boolean constructorInvokeIsSideEffectFree(InvokeMethod invoke) {
       DexMethod invokedMethod = invoke.getInvokedMethod();
       if (invokedMethod == charSequenceConstructor) {
-        // NullPointerException - if seq is null.
-        Value seqValue = invoke.inValues().get(1);
-        return !seqValue.getType().isNullable();
+        // Performs callbacks on the given CharSequence, which may have side effects.
+        TypeElement charSequenceType = invoke.getArgument(1).getType();
+        return charSequenceType.isClassType()
+            && charSequenceType.asClassType().getClassType() == stringType;
       }
 
       if (invokedMethod == defaultConstructor) {
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 04155b9..367a8f3 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -271,10 +271,18 @@
         return compareTo(other) > 0;
       }
 
+      public boolean isNewerThanOrEqual(Version other) {
+        return compareTo(other) >= 0;
+      }
+
       public boolean isAtLeast(Version other) {
         return compareTo(other) >= 0;
       }
 
+      public boolean isOlderThan(Version other) {
+        return compareTo(other) < 0;
+      }
+
       public boolean isOlderThanOrEqual(Version other) {
         return compareTo(other) <= 0;
       }
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/string/UnusedStringBuilderFromCharSequenceWithAppendObjectTest.java b/src/test/java/com/android/tools/r8/ir/optimize/string/UnusedStringBuilderFromCharSequenceWithAppendObjectTest.java
index 46dfe04..8f1f58b 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/string/UnusedStringBuilderFromCharSequenceWithAppendObjectTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/string/UnusedStringBuilderFromCharSequenceWithAppendObjectTest.java
@@ -7,6 +7,7 @@
 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 org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -33,13 +34,17 @@
         .setMinApi(parameters.getApiLevel())
         .compile()
         .run(parameters.getRuntime(), Main.class)
-        .assertSuccessWithEmptyOutput();
-    // TODO(christofferqa): Should succeed with output;
-    //  .assertSuccessWithOutputLines(
-    //      "CustomCharSequence.length()",
-    //      "CustomCharSequence.length()",
-    //      "CustomCharSequence.length()",
-    //      "CustomCharSequence.charAt(0)");
+        .assertSuccessWithOutputLinesIf(
+            parameters.isCfRuntime()
+                || parameters.getDexRuntimeVersion().isNewerThanOrEqual(Version.V7_0_0),
+            "CustomCharSequence.length()",
+            "CustomCharSequence.length()",
+            "CustomCharSequence.length()",
+            "CustomCharSequence.charAt(0)")
+        .assertSuccessWithOutputLinesIf(
+            parameters.isDexRuntime()
+                && parameters.getDexRuntimeVersion().isOlderThan(Version.V7_0_0),
+            "CustomCharSequence.toString()");
   }
 
   static class Main {
@@ -63,12 +68,18 @@
         throw new RuntimeException();
       }
       System.out.println("CustomCharSequence.charAt(0)");
-      return 0;
+      return 'A';
     }
 
     @Override
     public CharSequence subSequence(int i, int i1) {
       throw new RuntimeException();
     }
+
+    @Override
+    public String toString() {
+      System.out.println("CustomCharSequence.toString()");
+      return "A";
+    }
   }
 }