Files
sdk/tests/language/logical_expression_test.dart
T
floitsch@google.com 359e795074 GenerateNot was not respecting "generateAtUseSite".
This fixes a severe issue when the first condition of a logical-or was used
by more than one expression.

Example:
var cond = foo();
if (cond || bar()) ...
if (cond || gee()) ...

An intermediate step transformed this into:
var t1 = !foo();  // <== note the "!".
if (t1) if (bar()) -> jump to correct block
if (t1) if (gee()) -> jump to correct block.

The variable 't1' was marked as "not-generate-at-use-site", since it
was shared between the two 'ifs'.

Later we realize that we want to emit a logical or.

However, in the back-end we had an optimization that basically said:
if we produce a logical or, we have to invert the first argument.
if that argument is a Not, we can ignore the Not-node and use its expression
directly.

This jumped over the "not-generate-at-use-site" of the Not node, and
looked directly at "cond", which was allowed to be generated at
use-site (at the initialization of "t1").

BUG= http://dartbug.com/16996
R=sra@google.com

Review URL: https://codereview.chromium.org//175403002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@32951 260f80e4-7a28-3924-810f-c04153c831b5
2014-02-24 07:25:43 +00:00

120 lines
3.2 KiB
Dart

// 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();
}