Version 1.2.0-dev.5.15
svn merge -c 32927 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 32951 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
R=ricow@google.com
Review URL: https://codereview.chromium.org//177293002
git-svn-id: http://dart.googlecode.com/svn/trunk@32954 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index 4792747..ad93039 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -1817,6 +1817,8 @@
handledBySpecialCase = true;
if (input is HIs) {
emitIs(input, '!==');
+ } else if (input is HNot) {
+ use(input.inputs[0]);
} else if (input is HIdentity) {
HIdentity identity = input;
emitIdentityComparison(identity.left, identity.right, true);
@@ -1866,11 +1868,7 @@
} else if (node.inputs[1].isConstantBoolean()) {
String operation = node.inputs[1].isConstantFalse() ? '&&' : '||';
if (operation == '||') {
- if (input is HNot) {
- use(input.inputs[0]);
- } else {
- generateNot(input);
- }
+ generateNot(input);
} else {
use(input);
}
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 3bfe7a8..f73cebd 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -17,6 +17,8 @@
mirrors/relation_assignable_test: Fail # Issue 16736
mirrors/relation_subclass_test: Fail # Issue 16737
+logical_expression_test: Fail # Issue 17027
+
[ $mode == debug ]
mirror_final_field_inferrer2_test: Crash, Pass, Slow # dartbug.com/15581
diff --git a/tests/compiler/dart2js/logical_expression_test.dart b/tests/compiler/dart2js/logical_expression_test.dart
new file mode 100644
index 0000000..75d69e9
--- /dev/null
+++ b/tests/compiler/dart2js/logical_expression_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2014, the Dart 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.
+
+// Test that logical or-expressions don't introduce unnecessary nots.
+
+import "package:async_helper/async_helper.dart";
+import 'compiler_helper.dart';
+
+const String TEST_ONE = r"""
+foo(bar, gee) {
+ bool cond1 = bar();
+ if (cond1 || gee()) gee();
+ if (cond1 || gee()) gee();
+}
+""";
+
+const String TEST_TWO = r"""
+void foo(list, bar) {
+ if (list == null) bar();
+ if (list == null || bar()) bar();
+ if (list == null || bar()) bar();
+}
+""";
+
+main() {
+ // We want something like:
+ // var t1 = bar.call$0() === true;
+ // if (t1 || gee.call$0() === true) gee.call$0();
+ // if (t1 || gee.call$0() === true) gee.call$0();
+ compileAndDoNotMatchFuzzy(TEST_ONE, 'foo',
+ r"""var x = [a-zA-Z0-9$.]+\(\) == true;
+ if \(x \|\| [a-zA-Z0-9$.]+\(\) === true\) [^;]+;
+ if \(x \|\| [a-zA-Z0-9$.]+\(\) === true\) [^;]+;""");
+
+
+ // We want something like:
+ // var t1 = list == null;
+ // if (t1) bar.call$0();
+ // if (t1 || bar.call$0() === true) bar.call$0();
+ // if (t1 || bar.call$0() === true) bar.call$0();
+ compileAndMatchFuzzy(TEST_TWO, 'foo',
+ r"""var x = x == null;
+ if \(x\) [^;]+;
+ if \(x \|\| [a-zA-Z0-9$.]+\(\) === true\) [^;]+;
+ if \(x \|\| [a-zA-Z0-9$.]+\(\) === true\) [^;]+;""");
+}
diff --git a/tests/language/logical_expression_test.dart b/tests/language/logical_expression_test.dart
new file mode 100644
index 0000000..e3dd195
--- /dev/null
+++ b/tests/language/logical_expression_test.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2014, the Dart 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.
+// Dart test program for testing if statement.
+
+import "package:expect/expect.dart";
+
+// For logical-or conditions dart2js sometimes inlined expressions, leading to
+// completely broken programs.
+
+int globalCounter = 0;
+
+falseWithSideEffect() {
+ bool confuse() => new DateTime.now().millisecondsSinceEpoch == 42;
+
+ var result = confuse();
+
+ // Make it harder to inline.
+ if (result) {
+ try {
+ try {
+ if (confuse()) falseWithSideEffect();
+ if (confuse()) return 499;
+ } catch (e) {
+ rethrow;
+ }
+ } catch (e) {
+ rethrow;
+ }
+ }
+ globalCounter++;
+ return result;
+}
+
+falseWithoutSideEffect() {
+ bool confuse() => new DateTime.now().millisecondsSinceEpoch == 42;
+
+ var result = confuse();
+
+ // Make it harder to inline.
+ if (result) {
+ try {
+ try {
+ if (confuse()) falseWithSideEffect();
+ if (confuse()) return 499;
+ } catch (e) {
+ rethrow;
+ }
+ } catch (e) {
+ rethrow;
+ }
+ }
+ return result;
+}
+
+testLogicalOr() {
+ globalCounter = 0;
+ bool cond1 = falseWithSideEffect();
+ if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+ if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+ if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+ Expect.equals(1, globalCounter);
+
+ cond1 = (falseWithSideEffect() == 499);
+ if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+ if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+ if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
+ Expect.equals(2, globalCounter);
+}
+
+List globalList = [];
+void testLogicalOr2() {
+ globalList.clear();
+ testValueOr([]);
+ testValueOr(null);
+ Expect.listEquals([1, 2, 3], globalList);
+}
+
+void testValueOr(List list) {
+ if (list == null) globalList.add(1);
+ if (list == null || list.contains("2")) globalList.add(2);
+ if (list == null || list.contains("3")) globalList.add(3);
+}
+
+testLogicalAnd() {
+ globalCounter = 0;
+ bool cond1 = falseWithSideEffect();
+ if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+ if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+ if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+ Expect.equals(1, globalCounter);
+
+ cond1 = (falseWithSideEffect() == 499);
+ if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+ if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+ if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
+ Expect.equals(2, globalCounter);
+}
+
+void testLogicalAnd2() {
+ globalList.clear();
+ testValueAnd([]);
+ testValueAnd(null);
+ Expect.listEquals([1, 2, 3], globalList);
+}
+
+void testValueAnd(List list) {
+ if (list == null) globalList.add(1);
+ if (list == null && globalList.contains(1)) globalList.add(2);
+ if (list == null && globalList.contains(1)) globalList.add(3);
+}
+
+main() {
+ testLogicalOr();
+ testLogicalOr2();
+
+ testLogicalAnd();
+ testLogicalAnd2();
+}
diff --git a/tools/VERSION b/tools/VERSION
index 51c8aeb..2d4e26f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 2
PATCH 0
PRERELEASE 5
-PRERELEASE_PATCH 14
+PRERELEASE_PATCH 15