8185252: Unary minus and plus use wrong node Kind

Reviewed-by: sundar, hannesw
This commit is contained in:
Priya Lakshmi Muthuswamy 2017-08-10 15:19:17 +02:00 committed by Hannes Wallnöfer
parent 4b359d10e4
commit 25eea31231
14 changed files with 182 additions and 33 deletions

View File

@ -75,6 +75,8 @@ abstract class TreeImpl implements Tree {
return Kind.MULTIPLY;
case ASSIGN_MUL:
return Kind.MULTIPLY_ASSIGNMENT;
case POS:
return Kind.UNARY_PLUS;
case ADD:
return Kind.PLUS;
case INCPREFIX:
@ -83,6 +85,8 @@ abstract class TreeImpl implements Tree {
return Kind.POSTFIX_INCREMENT;
case ASSIGN_ADD:
return Kind.PLUS_ASSIGNMENT;
case NEG:
return Kind.UNARY_MINUS;
case SUB:
return Kind.MINUS;
case DECPREFIX:

View File

@ -1027,7 +1027,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
@Override
public boolean enterSUB(final UnaryNode unaryNode) {
public boolean enterNEG(final UnaryNode unaryNode) {
loadSUB(unaryNode, resultBounds);
return false;
}
@ -1105,7 +1105,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
@Override
public boolean enterADD(final UnaryNode unaryNode) {
public boolean enterPOS(final UnaryNode unaryNode) {
loadADD(unaryNode, resultBounds);
return false;
}

View File

@ -231,7 +231,7 @@ final class FoldConstants extends SimpleNodeVisitor implements Loggable {
LiteralNode<?> literalNode;
switch (parent.tokenType()) {
case ADD:
case POS:
if (rhsInteger) {
literalNode = LiteralNode.newInstance(token, finish, rhs.getInt32());
} else if (rhsType.isLong()) {
@ -240,7 +240,7 @@ final class FoldConstants extends SimpleNodeVisitor implements Loggable {
literalNode = LiteralNode.newInstance(token, finish, rhs.getNumber());
}
break;
case SUB:
case NEG:
if (rhsInteger && rhs.getInt32() != 0) { // @see test/script/basic/minuszero.js
literalNode = LiteralNode.newInstance(token, finish, -rhs.getInt32());
} else if (rhsType.isLong() && rhs.getLong() != 0L) {

View File

@ -317,7 +317,7 @@ final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
}
@Override
public Node leaveADD(final UnaryNode unaryNode) {
public Node leavePOS(final UnaryNode unaryNode) {
return unaryNodeWeight(unaryNode);
}
@ -348,7 +348,7 @@ final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
}
@Override
public Node leaveSUB(final UnaryNode unaryNode) {
public Node leaveNEG(final UnaryNode unaryNode) {
return unaryNodeWeight(unaryNode);
}

View File

@ -58,8 +58,8 @@ public final class UnaryNode extends Expression implements Assignment<Expression
private static final List<TokenType> CAN_OVERFLOW =
Collections.unmodifiableList(
Arrays.asList(new TokenType[] {
TokenType.ADD,
TokenType.SUB, //negate
TokenType.POS,
TokenType.NEG, //negate
TokenType.DECPREFIX,
TokenType.DECPOSTFIX,
TokenType.INCPREFIX,
@ -125,7 +125,7 @@ public final class UnaryNode extends Expression implements Assignment<Expression
@Override
public Type getWidestOperationType() {
switch (tokenType()) {
case ADD:
case POS:
final Type operandType = getExpression().getType();
if(operandType == Type.BOOLEAN) {
return Type.INT;
@ -134,7 +134,7 @@ public final class UnaryNode extends Expression implements Assignment<Expression
}
assert operandType.isNumeric();
return operandType;
case SUB:
case NEG:
// This might seems overly conservative until you consider that -0 can only be represented as a double.
return Type.NUMBER;
case NOT:
@ -182,8 +182,8 @@ public final class UnaryNode extends Expression implements Assignment<Expression
switch (tokenType()) {
case NEW:
return false;
case ADD:
case SUB:
case POS:
case NEG:
case NOT:
case BIT_NOT:
return expression.isLocal() && expression.getType().isJSPrimitive();

View File

@ -47,8 +47,8 @@ public abstract class NodeOperatorVisitor<T extends LexicalContext> extends Node
@Override
public boolean enterUnaryNode(final UnaryNode unaryNode) {
switch (unaryNode.tokenType()) {
case ADD:
return enterADD(unaryNode);
case POS:
return enterPOS(unaryNode);
case BIT_NOT:
return enterBIT_NOT(unaryNode);
case DELETE:
@ -57,8 +57,8 @@ public abstract class NodeOperatorVisitor<T extends LexicalContext> extends Node
return enterNEW(unaryNode);
case NOT:
return enterNOT(unaryNode);
case SUB:
return enterSUB(unaryNode);
case NEG:
return enterNEG(unaryNode);
case TYPEOF:
return enterTYPEOF(unaryNode);
case VOID:
@ -76,8 +76,8 @@ public abstract class NodeOperatorVisitor<T extends LexicalContext> extends Node
@Override
public final Node leaveUnaryNode(final UnaryNode unaryNode) {
switch (unaryNode.tokenType()) {
case ADD:
return leaveADD(unaryNode);
case POS:
return leavePOS(unaryNode);
case BIT_NOT:
return leaveBIT_NOT(unaryNode);
case DELETE:
@ -86,8 +86,8 @@ public abstract class NodeOperatorVisitor<T extends LexicalContext> extends Node
return leaveNEW(unaryNode);
case NOT:
return leaveNOT(unaryNode);
case SUB:
return leaveSUB(unaryNode);
case NEG:
return leaveNEG(unaryNode);
case TYPEOF:
return leaveTYPEOF(unaryNode);
case VOID:
@ -280,7 +280,7 @@ public abstract class NodeOperatorVisitor<T extends LexicalContext> extends Node
* @param unaryNode the node
* @return true if traversal should continue and node children be traversed, false otherwise
*/
public boolean enterADD(final UnaryNode unaryNode) {
public boolean enterPOS(final UnaryNode unaryNode) {
return enterDefault(unaryNode);
}
@ -290,7 +290,7 @@ public abstract class NodeOperatorVisitor<T extends LexicalContext> extends Node
* @param unaryNode the node
* @return processed node, which will replace the original one, or the original node
*/
public Node leaveADD(final UnaryNode unaryNode) {
public Node leavePOS(final UnaryNode unaryNode) {
return leaveDefault(unaryNode);
}
@ -400,7 +400,7 @@ public abstract class NodeOperatorVisitor<T extends LexicalContext> extends Node
* @param unaryNode the node
* @return true if traversal should continue and node children be traversed, false otherwise
*/
public boolean enterSUB(final UnaryNode unaryNode) {
public boolean enterNEG(final UnaryNode unaryNode) {
return enterDefault(unaryNode);
}
@ -410,7 +410,7 @@ public abstract class NodeOperatorVisitor<T extends LexicalContext> extends Node
* @param unaryNode the node
* @return processed node, which will replace the original one, or the original node
*/
public Node leaveSUB(final UnaryNode unaryNode) {
public Node leaveNEG(final UnaryNode unaryNode) {
return leaveDefault(unaryNode);
}

View File

@ -4391,10 +4391,15 @@ public class Parser extends AbstractParser implements Loggable {
appendStatement(new ExpressionStatement(unaryLine, unaryToken, finish, expr));
return LiteralNode.newInstance(unaryToken, finish, true);
}
case ADD:
case SUB: {
final TokenType opType = type;
next();
final Expression expr = unaryExpression();
return new UnaryNode(Token.recast(unaryToken, (opType == TokenType.ADD) ? TokenType.POS : TokenType.NEG), expr);
}
case VOID:
case TYPEOF:
case ADD:
case SUB:
case BIT_NOT:
case NOT:
next();

View File

@ -63,10 +63,12 @@ public enum TokenType {
RPAREN (BRACKET, ")", 0, true),
MUL (BINARY, "*", 13, true),
ASSIGN_MUL (BINARY, "*=", 2, false),
POS (UNARY, "+", 14, false),
ADD (BINARY, "+", 12, true),
INCPREFIX (UNARY, "++", 15, true),
ASSIGN_ADD (BINARY, "+=", 2, false),
COMMARIGHT (BINARY, ",", 1, true),
NEG (UNARY, "-", 14, false),
SUB (BINARY, "-", 12, true),
DECPREFIX (UNARY, "--", 15, true),
ASSIGN_SUB (BINARY, "-=", 2, false),

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Test that Unary minus and plus uses UNARY_MINUS and UNARY_PLUS node Kind
*
* @test
* @bug 8185252
* @option -scripting
* @run
*/
var parser = Java.type('jdk.nashorn.api.tree.Parser');
var tree = Java.type('jdk.nashorn.api.tree.Tree');
var list = Java.type('java.util.List');
var visitor = Java.type('jdk.nashorn.api.tree.SimpleTreeVisitorES5_1');
var cls = Java.type('java.lang.Class')
function convert (value) {
if (!value || typeof(value) != 'object') {
return value;
}
var obj = Object.bindProperties({}, value)
var result = {}
for (var i in obj) {
if (i == "lineMap") {
continue;
}
var val = obj[i]
// skip these ES6 specific properties to reduce noise
// in the output - unless there were set to true
if (typeof(val) == 'boolean' && val == false) {
switch (i) {
case "computed":
case "static":
case "restParameter":
case "this":
case "super":
case "star":
case "default":
case "starDefaultStar":
case "arrow":
case "generator":
case "let":
case "const":
continue;
}
}
if (typeof(val) == 'object') {
if (val instanceof cls) {
continue;
}
if (val instanceof tree) {
result[i] = convert(val)
}
else if (val instanceof list) {
var lst = []
for (var j in val) {
lst.push(convert(val[j]))
}
result[i] = lst
}
else {
result[i] = String(val)
}
} else if (typeof(val) != 'function') {
result[i] = String(val)
}
}
return result
}
function parse(name, code, args, visitor, listener) {
var tree = parser.create(args).parse(name, code, listener || null)
var results = []
tree.accept(visitor, results)
print(JSON.stringify(results, null, 2))
}
var code = <<EOF
+1;
-1;
EOF
parse("JDK-8185252.js", code, "-nse", new (Java.extend(visitor, {
visitUnary: function (node, obj) {
obj.push(convert(node))
}
})))

View File

@ -0,0 +1,24 @@
[
{
"expression": {
"endPosition": "3",
"kind": "NUMBER_LITERAL",
"value": "1",
"startPosition": "2"
},
"endPosition": "3",
"kind": "UNARY_PLUS",
"startPosition": "1"
},
{
"expression": {
"endPosition": "7",
"kind": "NUMBER_LITERAL",
"value": "1",
"startPosition": "6"
},
"endPosition": "7",
"kind": "UNARY_MINUS",
"startPosition": "5"
}
]

View File

@ -3983,7 +3983,7 @@
"startPosition": "1164"
},
"endPosition": "1165",
"kind": "PLUS",
"kind": "UNARY_PLUS",
"startPosition": "1163"
},
"endPosition": "1165",
@ -3999,7 +3999,7 @@
"startPosition": "1168"
},
"endPosition": "1169",
"kind": "MINUS",
"kind": "UNARY_MINUS",
"startPosition": "1167"
},
"endPosition": "1169",

View File

@ -75,8 +75,8 @@ in visitUnary POSTFIX_INCREMENT x
in visitUnary POSTFIX_DECREMENT x
in visitUnary PREFIX_INCREMENT x
in visitUnary PREFIX_DECREMENT x
in visitUnary PLUS x
in visitUnary MINUS x
in visitUnary UNARY_PLUS x
in visitUnary UNARY_MINUS x
in visitUnary BITWISE_COMPLEMENT x
in visitUnary LOGICAL_COMPLEMENT x
in visitUnary DELETE x

View File

@ -73,7 +73,7 @@
"startPosition": "121"
},
"endPosition": "122",
"kind": "MINUS",
"kind": "UNARY_MINUS",
"startPosition": "120"
},
"startPosition": "114"

View File

@ -84,7 +84,7 @@
"startPosition": "50"
},
"endPosition": "51",
"kind": "PLUS",
"kind": "UNARY_PLUS",
"startPosition": "49"
},
{
@ -95,7 +95,7 @@
"startPosition": "54"
},
"endPosition": "55",
"kind": "MINUS",
"kind": "UNARY_MINUS",
"startPosition": "53"
},
{