Add test for break to labeled statements.

Change-Id: Ia1d7e5f93426d2781c7b3b583af10d88af142f28
Reviewed-on: https://dart-review.googlesource.com/8044
Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
Johnni Winther
2017-09-27 09:38:53 +00:00
parent 7818726c3d
commit 01ca690a67
5 changed files with 83 additions and 7 deletions
+6 -7
View File
@@ -217,7 +217,7 @@ class JumpVisitor extends ir.Visitor {
@override
defaultNode(ir.Node node) => node.visitChildren(this);
bool _canBeBreakTarget(ir.TreeNode node) {
static bool canBeBreakTarget(ir.TreeNode node) {
return node is ir.ForStatement ||
node is ir.ForInStatement ||
node is ir.WhileStatement ||
@@ -225,8 +225,7 @@ class JumpVisitor extends ir.Visitor {
node is ir.SwitchStatement;
}
bool _canBeContinueTarget(ir.TreeNode node) {
// TODO(johnniwinther): Add more.
static bool canBeContinueTarget(ir.TreeNode node) {
return node is ir.ForStatement ||
node is ir.ForInStatement ||
node is ir.WhileStatement ||
@@ -238,7 +237,7 @@ class JumpVisitor extends ir.Visitor {
JJumpTarget target;
ir.TreeNode body = node.target.body;
ir.TreeNode parent = node.target.parent;
if (_canBeBreakTarget(body)) {
if (canBeBreakTarget(body)) {
// We have code like
//
// l1: for (int i = 0; i < 10; i++) {
@@ -251,7 +250,7 @@ class JumpVisitor extends ir.Visitor {
ir.TreeNode search = node;
bool needsLabel = false;
while (search != node.target) {
if (_canBeBreakTarget(search)) {
if (canBeBreakTarget(search)) {
needsLabel = search != body;
break;
}
@@ -261,7 +260,7 @@ class JumpVisitor extends ir.Visitor {
JLabelDefinition label = _getOrCreateLabel(target, node.target);
label.isBreakTarget = true;
}
} else if (_canBeContinueTarget(parent)) {
} else if (canBeContinueTarget(parent)) {
// We have code like
//
// for (int i = 0; i < 10; i++) l1: {
@@ -275,7 +274,7 @@ class JumpVisitor extends ir.Visitor {
ir.TreeNode search = node;
bool needsLabel = false;
while (search != node.target) {
if (_canBeContinueTarget(search)) {
if (canBeContinueTarget(search)) {
needsLabel = search != body;
break;
}
@@ -5,6 +5,7 @@
import 'package:compiler/src/common.dart';
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/kernel/element_map.dart';
import 'package:compiler/src/js_model/locals.dart';
import 'package:compiler/src/resolution/access_semantics.dart';
import 'package:compiler/src/resolution/send_structure.dart';
import 'package:compiler/src/resolution/tree_elements.dart';
@@ -293,6 +294,9 @@ abstract class AstDataExtractor extends ast.Visitor with DataRegistry {
return new NodeId(node.getBeginToken().charOffset, IdKind.moveNext);
}
NodeId createLabeledStatementId(ast.LabeledStatement node) =>
computeDefaultNodeId(node.statement);
NodeId createLoopId(ast.Node node) => computeDefaultNodeId(node);
NodeId createGotoId(ast.Node node) => computeDefaultNodeId(node);
@@ -413,6 +417,13 @@ abstract class AstDataExtractor extends ast.Visitor with DataRegistry {
visitNode(node);
}
visitLabeledStatement(ast.LabeledStatement node) {
if (node.statement is! ast.Loop && node.statement is! ast.SwitchStatement) {
computeForNode(node, createLabeledStatementId(node));
}
visitNode(node);
}
visitSwitchStatement(ast.SwitchStatement node) {
computeForNode(node, createSwitchId(node));
visitNode(node);
@@ -513,6 +524,8 @@ abstract class IrDataExtractor extends ir.Visitor with DataRegistry {
return new NodeId(node.fileOffset, IdKind.moveNext);
}
NodeId createLabeledStatementId(ir.LabeledStatement node) =>
computeDefaultNodeId(node.body);
NodeId createLoopId(ir.TreeNode node) => computeDefaultNodeId(node);
NodeId createGotoId(ir.TreeNode node) => computeDefaultNodeId(node);
NodeId createSwitchId(ir.SwitchStatement node) => computeDefaultNodeId(node);
@@ -604,6 +617,14 @@ abstract class IrDataExtractor extends ir.Visitor with DataRegistry {
super.visitWhileStatement(node);
}
visitLabeledStatement(ir.LabeledStatement node) {
if (!JumpVisitor.canBeBreakTarget(node.body) &&
!JumpVisitor.canBeContinueTarget(node.parent)) {
computeForNode(node, createLabeledStatementId(node));
}
super.visitLabeledStatement(node);
}
visitBreakStatement(ir.BreakStatement node) {
computeForNode(node, createGotoId(node));
super.visitBreakStatement(node);
@@ -117,6 +117,8 @@ class ComputerMixin {
String get switchName => 'switch';
String get switchCaseName => 'case';
String get labelName => 'label';
}
/// AST visitor for computing a descriptive mapping of the [Id]s in a member.
@@ -138,6 +140,8 @@ class ResolvedAstComputer extends AstDataExtractor with ComputerMixin {
return switchName;
} else if (node is ast.SwitchCase) {
return switchCaseName;
} else if (node is ast.LabeledStatement) {
return labelName;
}
dynamic sendStructure;
@@ -268,6 +272,8 @@ class IrComputer extends IrDataExtractor with ComputerMixin {
return switchName;
} else if (node is ir.SwitchCase) {
return switchCaseName;
} else if (node is ir.LabeledStatement) {
return labelName;
}
return '<unknown:$node (${node.runtimeType})>';
}
@@ -0,0 +1,26 @@
// Copyright (c) 2017, 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.
main() {
breakFromIf(true);
breakFromBlock(true);
}
breakFromIf(c) {
label:
/*0@break*/ if (c) {
/*target=0*/ break label;
}
}
breakFromBlock(c) {
label:
/*0@break*/
{
if (c) {
/*target=0*/ break label;
}
print('1');
}
}
@@ -159,6 +159,19 @@ class JumpsAstComputer extends AstDataExtractor with JumpsMixin {
super.visitGotoStatement(node);
}
@override
visitLabeledStatement(ast.LabeledStatement node) {
if (node.statement is! ast.Loop && node.statement is! ast.SwitchStatement) {
JumpTarget target = elements.getTargetDefinition(node.statement);
if (target != null) {
NodeId id = createLabeledStatementId(node);
SourceSpan sourceSpan = computeSourceSpan(node);
targets[target] = new TargetData(index++, id, sourceSpan, target);
}
}
super.visitLabeledStatement(node);
}
@override
visitSwitchStatement(ast.SwitchStatement node) {
JumpTarget target = elements.getTargetDefinition(node);
@@ -246,6 +259,17 @@ class JumpsIrChecker extends IrDataExtractor with JumpsMixin {
super.visitBreakStatement(node);
}
@override
visitLabeledStatement(ir.LabeledStatement node) {
JumpTarget target = _localsMap.getJumpTargetForLabel(node);
if (target != null) {
NodeId id = createLabeledStatementId(node);
SourceSpan sourceSpan = computeSourceSpan(node);
targets[target] = new TargetData(index++, id, sourceSpan, target);
}
super.visitLabeledStatement(node);
}
visitSwitchStatement(ir.SwitchStatement node) {
addTargetData(
node, createSwitchId(node), _localsMap.getJumpTargetForSwitch(node));