Handle used postfix and (used) prefix in inferrer
Change-Id: Ia8befd70a937aeb4a8f0f32f98b28f0e6ec39f73 Reviewed-on: https://dart-review.googlesource.com/3886 Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
6c81e20c83
commit
54b57079a3
@@ -322,4 +322,10 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
||||
receiverType, _analyzedMember, arguments, _sideEffects,
|
||||
inLoop: inLoop, isConditional: false);
|
||||
}
|
||||
|
||||
@override
|
||||
TypeInformation visitLet(ir.Let node) {
|
||||
visit(node.variable);
|
||||
return visit(node.body);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,7 +345,9 @@ abstract class AstDataExtractor extends ast.Visitor with DataRegistry {
|
||||
computeForNode(node, createUpdateId(position));
|
||||
}
|
||||
break;
|
||||
case SendStructureKind.PREFIX:
|
||||
case SendStructureKind.POSTFIX:
|
||||
case SendStructureKind.COMPOUND:
|
||||
computeForNode(node, createAccessId(node.selector));
|
||||
computeForNode(node, createInvokeId(node.assignmentOperator));
|
||||
computeForNode(node, createUpdateId(node.selector));
|
||||
@@ -425,17 +427,20 @@ abstract class IrDataExtractor extends ir.Visitor with DataRegistry {
|
||||
}
|
||||
|
||||
NodeId computeDefaultNodeId(ir.TreeNode node) {
|
||||
assert(node.fileOffset != ir.TreeNode.noOffset);
|
||||
assert(node.fileOffset != ir.TreeNode.noOffset,
|
||||
"No fileOffset on $node (${node.runtimeType})");
|
||||
return new NodeId(node.fileOffset, IdKind.node);
|
||||
}
|
||||
|
||||
NodeId createInvokeId(ir.TreeNode node) {
|
||||
assert(node.fileOffset != ir.TreeNode.noOffset);
|
||||
assert(node.fileOffset != ir.TreeNode.noOffset,
|
||||
"No fileOffset on ${node} (${node.runtimeType})");
|
||||
return new NodeId(node.fileOffset, IdKind.invoke);
|
||||
}
|
||||
|
||||
NodeId createUpdateId(ir.TreeNode node) {
|
||||
assert(node.fileOffset != ir.TreeNode.noOffset);
|
||||
assert(node.fileOffset != ir.TreeNode.noOffset,
|
||||
"No fileOffset on ${node} (${node.runtimeType})");
|
||||
return new NodeId(node.fileOffset, IdKind.update);
|
||||
}
|
||||
|
||||
@@ -469,7 +474,8 @@ abstract class IrDataExtractor extends ir.Visitor with DataRegistry {
|
||||
}
|
||||
|
||||
visitVariableDeclaration(ir.VariableDeclaration node) {
|
||||
if (node.parent is! ir.FunctionDeclaration) {
|
||||
if (node.name != null && node.parent is! ir.FunctionDeclaration) {
|
||||
// Skip synthetic variables and function declaration variables.
|
||||
computeForNode(node, computeDefaultNodeId(node));
|
||||
}
|
||||
super.visitVariableDeclaration(node);
|
||||
@@ -486,7 +492,10 @@ abstract class IrDataExtractor extends ir.Visitor with DataRegistry {
|
||||
}
|
||||
|
||||
visitVariableGet(ir.VariableGet node) {
|
||||
computeForNode(node, computeDefaultNodeId(node));
|
||||
if (node.variable.name != null) {
|
||||
// Skip use of synthetic variables.
|
||||
computeForNode(node, computeDefaultNodeId(node));
|
||||
}
|
||||
super.visitVariableGet(node);
|
||||
}
|
||||
|
||||
@@ -496,7 +505,10 @@ abstract class IrDataExtractor extends ir.Visitor with DataRegistry {
|
||||
}
|
||||
|
||||
visitVariableSet(ir.VariableSet node) {
|
||||
computeForNode(node, createUpdateId(node));
|
||||
if (node.variable.name != null) {
|
||||
// Skip use of synthetic variables.
|
||||
computeForNode(node, createUpdateId(node));
|
||||
}
|
||||
super.visitVariableSet(node);
|
||||
}
|
||||
|
||||
|
||||
@@ -292,6 +292,8 @@ Map<Id, IdValue> computeExpectedMap(AnnotatedCode code) {
|
||||
Map<Id, IdValue> map = <Id, IdValue>{};
|
||||
for (Annotation annotation in code.annotations) {
|
||||
IdValue idValue = IdValue.decode(annotation.offset, annotation.text);
|
||||
Expect.isFalse(map.containsKey(idValue.id),
|
||||
"Duplicate annotations for ${idValue.id}.");
|
||||
map[idValue.id] = idValue;
|
||||
}
|
||||
return map;
|
||||
|
||||
@@ -182,7 +182,9 @@ class ResolvedAstComputer extends AstDataExtractor with ComputerMixin {
|
||||
String dynamicName = getDynamicName();
|
||||
if (dynamicName != null) return computeSetName(dynamicName);
|
||||
break;
|
||||
case SendStructureKind.PREFIX:
|
||||
case SendStructureKind.POSTFIX:
|
||||
case SendStructureKind.COMPOUND:
|
||||
String dynamicName = getDynamicName();
|
||||
if (dynamicName != null) {
|
||||
if (id.kind == IdKind.update) {
|
||||
|
||||
@@ -9,6 +9,10 @@ main() {
|
||||
updatedLocal();
|
||||
invokeLocal();
|
||||
postfixLocal();
|
||||
postfixLocalUsed();
|
||||
prefixLocal();
|
||||
prefixLocalUsed();
|
||||
complexAssignmentLocal();
|
||||
}
|
||||
|
||||
/*element: uninitializedLocal:[null]*/
|
||||
@@ -44,3 +48,29 @@ postfixLocal() {
|
||||
local2 /*invoke: [exact=JSUInt31]*/ ++;
|
||||
return null;
|
||||
}
|
||||
|
||||
/*element: postfixLocalUsed:[exact=JSUInt31]*/
|
||||
postfixLocalUsed() {
|
||||
var local2 = 0;
|
||||
return local2 /*invoke: [exact=JSUInt31]*/ ++;
|
||||
}
|
||||
|
||||
/*element: prefixLocal:[null]*/
|
||||
prefixLocal() {
|
||||
// ignore: UNUSED_LOCAL_VARIABLE
|
||||
var local2 = 0;
|
||||
/*invoke: [exact=JSUInt31]*/ ++local2;
|
||||
return null;
|
||||
}
|
||||
|
||||
/*element: prefixLocalUsed:[subclass=JSUInt32]*/
|
||||
prefixLocalUsed() {
|
||||
var local2 = 0;
|
||||
return /*invoke: [exact=JSUInt31]*/ ++local2;
|
||||
}
|
||||
|
||||
/*element: complexAssignmentLocal:[subclass=JSUInt32]*/
|
||||
complexAssignmentLocal() {
|
||||
var local2 = 0;
|
||||
return local2 /*invoke: [exact=JSUInt31]*/ += 42;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user