blob: 9226b206b6c941782122a47a350a12f650cad586 [file] [log] [blame]
// 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 = 2.9
// This test broke dart2js.
// A compiler must not construct a critical edge on this program.
//
// In particular we have to watch out for:
// - the while-loop branch going to the body-block and to the exit-block, and
// - the exit-block having as incoming the condition-block and the
// break-blocks.
//
// Triggering the bug is relatively hard, since pushing instructions back the
// exit-block to the incoming blocks is not guaranteed to trigger an error.
// Dart2js frequently ended up with update-assignments just before the
// condition:
// for (int i = 0; state = state0, i < 10; i++) {
// if (..) { state = 1; }
// ...
// }
// use(state);
//
// In this case the "state" variable was assigned before the loop and then
// reassigned before the break. The exit-block pushed the assignment back
// to its incoming blocks and that's why the "state = state0" assignment ended
// up just before the condition.
// Note that the assignment was executed at every iteration instead of just
// when exiting the loop.
// This repeated assignments don't have any negative effect unless the state
// variable is also assigned and used inside the loop-body. It turns out that
// this is very rare and needs some tricks to make happen.
import "package:expect/expect.dart";
String parse(String uri) {
int index = 0;
int char = -1;
void parseAuth() {
index;
char;
}
int state = 0;
while (true) {
char = uri.codeUnitAt(index);
if (char == 1234) {
state = (index == 0) ? 1 : 2;
break;
}
if (char == 0x3A) {
return "good";
}
index++;
}
if (state == 1) {
print(char == 1234);
print(index == uri.length);
}
return "bad";
}
main() {
Expect.equals("good", parse("dart:_foreign_helper"));
}