Make variables assigned in a loop not definitely unassigned anywhere in the loop.

Bug: https://github.com/dart-lang/sdk/issues/42301
Change-Id: I75962b976427cef7f40025f1dcd9f27400306825
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151047
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2020-06-15 17:29:05 +00:00 committed by commit-bot@chromium.org
parent 28231a790b
commit a1fc2ea80c
5 changed files with 90 additions and 18 deletions

View file

@ -1270,6 +1270,7 @@ class FlowModel<Variable, Type> {
Iterable<Variable> writtenVariables,
Iterable<Variable> capturedVariables) {
Map<Variable, VariableModel<Variable, Type>> newVariableInfo;
for (Variable variable in writtenVariables) {
VariableModel<Variable, Type> info = infoFor(variable);
if (info.promotedTypes != null) {
@ -1278,6 +1279,7 @@ class FlowModel<Variable, Type> {
variableInfo))[variable] = info.discardPromotions();
}
}
for (Variable variable in capturedVariables) {
VariableModel<Variable, Type> info = variableInfo[variable];
if (info == null) {
@ -1291,8 +1293,14 @@ class FlowModel<Variable, Type> {
variableInfo))[variable] = info.writeCapture();
}
}
if (newVariableInfo == null) return this;
return new FlowModel<Variable, Type>._(reachable, newVariableInfo);
FlowModel<Variable, Type> result = newVariableInfo == null
? this
: new FlowModel<Variable, Type>._(reachable, newVariableInfo);
result = result.joinUnassigned(written: writtenVariables);
return result;
}
/// Updates the state to reflect a control path that is known to have
@ -2433,8 +2441,6 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
@override
void for_end() {
FlowModel<Variable, Type> afterUpdate = _current;
_WhileContext<Variable, Type> context =
_stack.removeLast() as _WhileContext<Variable, Type>;
// Tail of the stack: falseCondition, break
@ -2442,7 +2448,6 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
FlowModel<Variable, Type> falseCondition = context._conditionInfo.ifFalse;
_current = _join(falseCondition, breakState);
_current = _current.joinUnassigned(other: afterUpdate);
}
@override
@ -2481,9 +2486,6 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
_stack.add(new _SimpleContext(_current));
_current = _current.removePromotedAll(_assignedVariables._anywhere._written,
_assignedVariables._anywhere._captured);
_current = _current.joinUnassigned(
written: _assignedVariables._anywhere._written,
);
}
@override
@ -2752,9 +2754,8 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
AssignedVariablesNodeInfo<Variable> info =
_assignedVariables._getInfoForNode(body);
FlowModel<Variable, Type> beforeCatch = beforeBody
.removePromotedAll(info._written, info._captured)
.joinUnassigned(other: afterBody);
FlowModel<Variable, Type> beforeCatch =
beforeBody.removePromotedAll(info._written, info._captured);
context._beforeCatch = beforeCatch;
context._afterBodyAndCatches = afterBody;
@ -2843,9 +2844,7 @@ class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
void whileStatement_end() {
_WhileContext<Variable, Type> context =
_stack.removeLast() as _WhileContext<Variable, Type>;
FlowModel<Variable, Type> afterBody = _current;
_current = _join(context._conditionInfo.ifFalse, context._breakModel);
_current = _current.joinUnassigned(other: afterBody);
}
@override

View file

@ -40,7 +40,7 @@ breakOuterFromInner(bool c) {
condition() {
late int v1, v2;
do {
/*unassigned*/ v1; // assigned in the condition, but not yet
v1;
} while ((v1 = 0) + (v2 = 0) >= 0);
v2;
}

View file

@ -2,6 +2,56 @@
// 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.
for_assignedInBody_body(bool b) {
late int v;
for (;;) {
if (b) {
v = 0;
} else {
v;
}
v;
}
v;
}
for_assignedInBody_condition() {
bool firstTime = true;
late int v;
for (; firstTime || v > 0;) {
firstTime = false;
v = 5;
}
v;
}
for_assignedInBody_initializer() {
bool firstTime = true;
late int v;
for (var x = /*unassigned*/ v;;) {
v = 5;
}
v;
}
for_assignedInCondition() {
bool firstTime = true;
late int v;
for (var x = /*unassigned*/ v; (v = 0) > 0;) {
v;
}
v;
}
for_assignedInUpdater() {
bool firstTime = true;
late int v;
for (var x = /*unassigned*/ v;; v = 0) {
v;
}
v;
}
for_body(bool c) {
late int v;
for (; c;) {
@ -77,7 +127,7 @@ for_initializer_variable() {
for_updaters(bool c) {
late int v1, v2, v3, v4;
for (; c; v1 = 0, v2 = 0, v3 = 0, /*unassigned*/ v4) {
/*unassigned*/ v1;
v1;
}
v2;
}
@ -115,7 +165,7 @@ collection_for_initializer_variable() {
collection_for_updaters(bool c) {
late int v1, v2, v3, v4;
[for (; c; v1 = 0, v2 = 0, v3 = 0, /*unassigned*/ v4) /*unassigned*/ v1 ];
[for (; c; v1 = 0, v2 = 0, v3 = 0, /*unassigned*/ v4) v1];
v2;
}

View file

@ -8,7 +8,7 @@ void method1() {
local = 0;
return;
} finally {
print(/*unassigned*/ local);
print(local);
}
local;
}
@ -22,7 +22,7 @@ void method2() {
local = 42;
rethrow;
} finally {
print(/*unassigned*/ local);
print(local);
}
local;
}

View file

@ -2,6 +2,29 @@
// 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.
assignedInBody_body(bool b) {
late int v;
while (true) {
if (b) {
v = 0;
} else {
v;
}
v;
}
v;
}
assignedInBody_condition() {
bool firstTime = true;
late int v;
while (firstTime || v > 0) {
firstTime = false;
v = 5;
}
v;
}
condition() {
late int v;
while ((v = 0) >= 0) {