From: jzhou Date: Fri, 28 Jan 2011 01:58:29 +0000 (+0000) Subject: Fix the bug of assignment conversion: 'short s = 12' should be allowed. And for such... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=e5ae1eb173433366e748a2973be2cdbdcfcd83e0;p=IRC.git Fix the bug of assignment conversion: 'short s = 12' should be allowed. And for such case, in BuildFlat.java the right side of the assignment is replaced with the value. --- diff --git a/Robust/src/IR/FieldDescriptor.java b/Robust/src/IR/FieldDescriptor.java index a60a65d3..ce515321 100644 --- a/Robust/src/IR/FieldDescriptor.java +++ b/Robust/src/IR/FieldDescriptor.java @@ -52,6 +52,10 @@ public class FieldDescriptor extends Descriptor { return en; } + public boolean isFinal() { + return modifier.isFinal(); + } + public boolean isStatic() { return modifier.isStatic(); } diff --git a/Robust/src/IR/Flat/BuildFlat.java b/Robust/src/IR/Flat/BuildFlat.java index 48b07b78..c9f4b783 100644 --- a/Robust/src/IR/Flat/BuildFlat.java +++ b/Robust/src/IR/Flat/BuildFlat.java @@ -542,9 +542,13 @@ public class BuildFlat { //Get src value if (an.getSrc()!=null) { - NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp); - first=np_src.getBegin(); - last=np_src.getEnd(); + if(an.getSrc().getEval() != null) { + first = last = new FlatLiteralNode(an.getSrc().getType(), an.getSrc().getEval().longValue(), src_tmp); + } else { + NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp); + first=np_src.getBegin(); + last=np_src.getEnd(); + } } else if (!pre) { FlatLiteralNode fln=new FlatLiteralNode(new TypeDescriptor(TypeDescriptor.INT),new Integer(1),src_tmp); first=fln; diff --git a/Robust/src/IR/Tree/ArrayAccessNode.java b/Robust/src/IR/Tree/ArrayAccessNode.java index 46ca5612..a88004fd 100644 --- a/Robust/src/IR/Tree/ArrayAccessNode.java +++ b/Robust/src/IR/Tree/ArrayAccessNode.java @@ -38,4 +38,9 @@ public class ArrayAccessNode extends ExpressionNode { else return left.getType().dereference(); } + + public Long evaluate() { + eval = null; + return eval; //null; + } } diff --git a/Robust/src/IR/Tree/ArrayInitializerNode.java b/Robust/src/IR/Tree/ArrayInitializerNode.java index e6bc7b33..5c12ffe3 100644 --- a/Robust/src/IR/Tree/ArrayInitializerNode.java +++ b/Robust/src/IR/Tree/ArrayInitializerNode.java @@ -43,4 +43,9 @@ public class ArrayInitializerNode extends ExpressionNode { public int kind() { return Kind.ArrayInitializerNode; } + + public Long evaluate() { + eval = null; + return eval; //null; + } } diff --git a/Robust/src/IR/Tree/AssignmentNode.java b/Robust/src/IR/Tree/AssignmentNode.java index 9d6b8ab9..abe6d41f 100644 --- a/Robust/src/IR/Tree/AssignmentNode.java +++ b/Robust/src/IR/Tree/AssignmentNode.java @@ -39,4 +39,9 @@ public class AssignmentNode extends ExpressionNode { public int kind() { return Kind.AssignmentNode; } + + public Long evaluate() { + eval = left.evaluate(); + return eval; + } } diff --git a/Robust/src/IR/Tree/CastNode.java b/Robust/src/IR/Tree/CastNode.java index e7e41c5f..d3267ebd 100644 --- a/Robust/src/IR/Tree/CastNode.java +++ b/Robust/src/IR/Tree/CastNode.java @@ -44,4 +44,9 @@ public class CastNode extends ExpressionNode { public int kind() { return Kind.CastNode; } + + public Long evaluate() { + eval = exp.evaluate(); + return eval; + } } diff --git a/Robust/src/IR/Tree/ClassTypeNode.java b/Robust/src/IR/Tree/ClassTypeNode.java index 18a7b000..b07e0ef8 100644 --- a/Robust/src/IR/Tree/ClassTypeNode.java +++ b/Robust/src/IR/Tree/ClassTypeNode.java @@ -28,4 +28,9 @@ public class ClassTypeNode extends ExpressionNode { public int kind() { return Kind.ClassTypeNode; } + + public Long evaluate() { + eval = null; + return eval; //null; + } } diff --git a/Robust/src/IR/Tree/CreateObjectNode.java b/Robust/src/IR/Tree/CreateObjectNode.java index ccc5f3a2..ebe23e7a 100644 --- a/Robust/src/IR/Tree/CreateObjectNode.java +++ b/Robust/src/IR/Tree/CreateObjectNode.java @@ -100,4 +100,9 @@ public class CreateObjectNode extends ExpressionNode { public int kind() { return Kind.CreateObjectNode; } + + public Long evaluate() { + eval = null; + return eval; //null; + } } diff --git a/Robust/src/IR/Tree/ExpressionNode.java b/Robust/src/IR/Tree/ExpressionNode.java index b6e4a476..1b80cc35 100644 --- a/Robust/src/IR/Tree/ExpressionNode.java +++ b/Robust/src/IR/Tree/ExpressionNode.java @@ -2,6 +2,8 @@ package IR.Tree; import IR.TypeDescriptor; public class ExpressionNode extends TreeNode { + Long eval = null; + public TypeDescriptor getType() { throw new Error(); } @@ -9,4 +11,12 @@ public class ExpressionNode extends TreeNode { public String printNode(int indentlevel) { return null; } + + public Long evaluate() { + throw new Error(); + } + + public Long getEval() { + return this.eval; + } } diff --git a/Robust/src/IR/Tree/FieldAccessNode.java b/Robust/src/IR/Tree/FieldAccessNode.java index 9a06ee44..151478cd 100644 --- a/Robust/src/IR/Tree/FieldAccessNode.java +++ b/Robust/src/IR/Tree/FieldAccessNode.java @@ -38,4 +38,14 @@ public class FieldAccessNode extends ExpressionNode { return getField().getType(); } + public Long evaluate() { + // if the field is a constant value then OK + eval = null; + if(field.isStatic() && field.isFinal()) { + eval = field.getExpressionNode().evaluate(); + } else if (field.isEnum()) { + eval = Long.valueOf((long)field.enumValue()); + } + return eval; + } } diff --git a/Robust/src/IR/Tree/InstanceOfNode.java b/Robust/src/IR/Tree/InstanceOfNode.java index 95d55ddb..bf015614 100644 --- a/Robust/src/IR/Tree/InstanceOfNode.java +++ b/Robust/src/IR/Tree/InstanceOfNode.java @@ -30,4 +30,9 @@ public class InstanceOfNode extends ExpressionNode { public int kind() { return Kind.InstanceOfNode; } + + public Long evaluate() { + eval = null; + return eval; //null; + } } diff --git a/Robust/src/IR/Tree/LiteralNode.java b/Robust/src/IR/Tree/LiteralNode.java index 9c64184c..e975c19e 100644 --- a/Robust/src/IR/Tree/LiteralNode.java +++ b/Robust/src/IR/Tree/LiteralNode.java @@ -60,4 +60,12 @@ public class LiteralNode extends ExpressionNode { public int kind() { return Kind.LiteralNode; } + + public Long evaluate() { + eval = null; + if(this.type.isChar() || this.type.isInt()) { + eval = Long.parseLong(this.value.toString()); + } + return eval; + } } diff --git a/Robust/src/IR/Tree/MethodInvokeNode.java b/Robust/src/IR/Tree/MethodInvokeNode.java index 6925b5e4..0ace6405 100644 --- a/Robust/src/IR/Tree/MethodInvokeNode.java +++ b/Robust/src/IR/Tree/MethodInvokeNode.java @@ -87,4 +87,9 @@ public class MethodInvokeNode extends ExpressionNode { public int kind() { return Kind.MethodInvokeNode; } + + public Long evaluate() { + eval = null; + return eval; //null; + } } diff --git a/Robust/src/IR/Tree/NameNode.java b/Robust/src/IR/Tree/NameNode.java index e2634647..1785b23a 100644 --- a/Robust/src/IR/Tree/NameNode.java +++ b/Robust/src/IR/Tree/NameNode.java @@ -97,4 +97,18 @@ public class NameNode extends ExpressionNode { public int kind() { return Kind.NameNode; } + + public Long evaluate() { + eval = null; + if(fd != null ) { + if(fd.isFinal() && fd.isStatic()) { + eval = fd.getExpressionNode().evaluate(); + } else if(fd.isEnum()) { + eval = Long.valueOf((long)fd.enumValue()); + } + } else if(en!= null) { + eval = en.evaluate(); + } + return eval; //null; + } } diff --git a/Robust/src/IR/Tree/OffsetNode.java b/Robust/src/IR/Tree/OffsetNode.java index 74ba651d..c293b869 100644 --- a/Robust/src/IR/Tree/OffsetNode.java +++ b/Robust/src/IR/Tree/OffsetNode.java @@ -41,4 +41,9 @@ public class OffsetNode extends ExpressionNode { public int kind() { return Kind.OffsetNode; } + + public Long evaluate() { + eval = null; + return eval; //null; + } } diff --git a/Robust/src/IR/Tree/OpNode.java b/Robust/src/IR/Tree/OpNode.java index 815f4894..d2a9dc81 100644 --- a/Robust/src/IR/Tree/OpNode.java +++ b/Robust/src/IR/Tree/OpNode.java @@ -68,4 +68,65 @@ public class OpNode extends ExpressionNode { public int kind() { return Kind.OpNode; } + + public Long evaluate() { + eval = null; + Long l = this.left.evaluate(); + if(l != null) { + if (this.op.getOp() == Operation.LOGIC_NOT) + eval = Long.valueOf(l.longValue() > 0 ? 0 : 1); + else if (this.op.getOp() == Operation.COMP) + eval = Long.valueOf((long)(~l.longValue())); + else { + Long r = this.right.evaluate(); + if(r != null) { + //if (this.op.getOp() == Operation.LOGIC_OR) + // return Long.valueOf((long)(l.longValue() || r.longValue())); + //else if (this.op.getOp() == Operation.LOGIC_AND) + // return Long.valueOf((long)(l.longValue() && r.longValue())); + /*else */if (this.op.getOp() == Operation.BIT_OR) + eval = Long.valueOf(l.longValue() | r.longValue()); + else if (this.op.getOp() == Operation.BIT_XOR) + eval = Long.valueOf(l.longValue() ^ r.longValue()); + else if (this.op.getOp() == Operation.BIT_AND) + eval = Long.valueOf(l.longValue() & r.longValue()); + else if (this.op.getOp() == Operation.EQUAL) + eval = Long.valueOf((l.longValue() == r.longValue())?1:0); + else if (this.op.getOp() == Operation.NOTEQUAL) + eval = Long.valueOf((l.longValue() != r.longValue())?1:0); + else if (this.op.getOp() == Operation.LT) + eval = Long.valueOf((l.longValue() < r.longValue())?1:0); + else if (this.op.getOp() == Operation.GT) + eval = Long.valueOf((l.longValue() > r.longValue())?1:0); + else if (this.op.getOp() == Operation.LTE) + eval = Long.valueOf((l.longValue() <= r.longValue())?1:0); + else if (this.op.getOp() == Operation.GTE) + eval = Long.valueOf((l.longValue() >= r.longValue())?1:0); + else if (this.op.getOp() == Operation.LEFTSHIFT) + eval = Long.valueOf(l.longValue() << r.longValue()); + else if (this.op.getOp() == Operation.RIGHTSHIFT) + eval = Long.valueOf(l.longValue() >> r.longValue()); + else if (this.op.getOp() == Operation.URIGHTSHIFT) + eval = Long.valueOf(l.longValue() >>> r.longValue()); + else if (this.op.getOp() == Operation.SUB) + eval = Long.valueOf(l.longValue() - r.longValue()); + else if (this.op.getOp() == Operation.ADD) + eval = Long.valueOf(l.longValue() + r.longValue()); + else if (this.op.getOp() == Operation.MULT) + eval = Long.valueOf(l.longValue() * r.longValue()); + else if (this.op.getOp() == Operation.DIV) + eval = Long.valueOf(l.longValue() / r.longValue()); + else if (this.op.getOp() == Operation.MOD) + eval = Long.valueOf(l.longValue() % r.longValue()); + else if (this.op.getOp() == Operation.UNARYPLUS) + eval = Long.valueOf(+l.longValue()); + else if (this.op.getOp() == Operation.UNARYMINUS) + eval = Long.valueOf(-l.longValue() ); + else if (this.op.getOp() == Operation.ASSIGN) + eval = Long.valueOf(r.longValue()); + } + } + } + return eval; + } } diff --git a/Robust/src/IR/Tree/SemanticCheck.java b/Robust/src/IR/Tree/SemanticCheck.java index be2e490a..6b057ed5 100644 --- a/Robust/src/IR/Tree/SemanticCheck.java +++ b/Robust/src/IR/Tree/SemanticCheck.java @@ -588,8 +588,12 @@ public class SemanticCheck { fd = new FieldDescriptor(new Modifiers(Modifiers.PUBLIC|Modifiers.FINAL), new TypeDescriptor(TypeDescriptor.INT), fieldname, null, false); fd.setAsEnum(); fd.setEnumValue(value); - } else if(!fd.isStatic()) { + } else if(fd.isStatic()) { // check if this field is a static field + if(fd.getExpressionNode() != null) { + checkExpressionNode(md,nametable,fd.getExpressionNode(),null); + } + } else { throw new Error("Dereference of the non-static field "+ fieldname + " in "+fan.printNode(0)+" in "+md); } } @@ -656,8 +660,25 @@ public class SemanticCheck { } if (td!=null) - if (!typeutil.isSuperorType(td,ln.getType())) - throw new Error("Field node returns "+ln.getType()+", but need "+td+" in "+md); + if (!typeutil.isSuperorType(td,ln.getType())) { + Long l = ln.evaluate(); + if((ln.getType().isByte() || ln.getType().isShort() + || ln.getType().isChar() || ln.getType().isInt()) + && (l != null) + && (td.isByte() || td.isShort() || td.isChar() + || td.isInt() || td.isLong())) { + long lnvalue = l.longValue(); + if((td.isByte() && ((lnvalue > 127) || (lnvalue < -128))) + || (td.isShort() && ((lnvalue > 32767) || (lnvalue < -32768))) + || (td.isChar() && ((lnvalue > 65535) || (lnvalue < 0))) + || (td.isInt() && ((lnvalue > 2147483647) || (lnvalue < -2147483648))) + || (td.isLong() && ((lnvalue > 9223372036854775807L) || (lnvalue < -9223372036854775808L)))) { + throw new Error("Field node returns "+ln.getType()+", but need "+td+" in "+md); + } + } else { + throw new Error("Field node returns "+ln.getType()+", but need "+td+" in "+md); + } + } } void checkNameNode(Descriptor md, SymbolTable nametable, NameNode nn, TypeDescriptor td) { @@ -860,7 +881,23 @@ public class SemanticCheck { } if (!postinc&&!typeutil.isSuperorType(an.getDest().getType(),an.getSrc().getType())) { - throw new Error("Type of rside ("+an.getSrc().getType().toPrettyString()+") not compatible with type of lside ("+an.getDest().getType().toPrettyString()+")"+an.printNode(0)); + TypeDescriptor dt = an.getDest().getType(); + TypeDescriptor st = an.getSrc().getType(); + Long l = an.getSrc().evaluate(); + if((st.isByte() || st.isShort() || st.isChar() || st.isInt()) + && (l != null) + && (dt.isByte() || dt.isShort() || dt.isChar() || dt.isInt() || dt.isLong())) { + long lnvalue = l.longValue(); + if((dt.isByte() && ((lnvalue > 127) || (lnvalue < -128))) + || (dt.isShort() && ((lnvalue > 32767) || (lnvalue < -32768))) + || (dt.isChar() && ((lnvalue > 65535) || (lnvalue < 0))) + || (dt.isInt() && ((lnvalue > 2147483647) || (lnvalue < -2147483648))) + || (dt.isLong() && ((lnvalue > 9223372036854775807L) || (lnvalue < -9223372036854775808L)))) { + throw new Error("Field node returns "+st+", but need "+dt+" in "+md); + } + } else { + throw new Error("Type of rside ("+an.getSrc().getType().toPrettyString()+") not compatible with type of lside ("+an.getDest().getType().toPrettyString()+")"+an.printNode(0)); + } } } diff --git a/Robust/src/IR/Tree/TertiaryNode.java b/Robust/src/IR/Tree/TertiaryNode.java index 09982865..4da59212 100644 --- a/Robust/src/IR/Tree/TertiaryNode.java +++ b/Robust/src/IR/Tree/TertiaryNode.java @@ -37,4 +37,23 @@ public class TertiaryNode extends ExpressionNode { public int kind() { return Kind.TertiaryNode; } + + public Long evaluate() { + eval = null; + Long c = this.cond.evaluate(); + if(c != null) { + Long t = this.trueExpr.evaluate(); + if(t != null) { + Long f = this.falseExpr.evaluate(); + if(f != null) { + if(c.intValue() > 0) { + eval = t; + } else { + eval = f; + } + } + } + } + return eval; + } } \ No newline at end of file diff --git a/Robust/src/Tests/AssignmentConversionTest.java b/Robust/src/Tests/AssignmentConversionTest.java new file mode 100644 index 00000000..3e746f94 --- /dev/null +++ b/Robust/src/Tests/AssignmentConversionTest.java @@ -0,0 +1,61 @@ +class AssignmentConversionTest { + public static final int sfi = 100; + + public static void main(String[] args) { + short s = 12; // narrow 12 to short + float f = s; // widen short to float + System.out.println("f=12 : " + (int)f); + + char c = '\u0009'; + int l = c; // widen char to int + System.out.println("l=0x9 : 0x" + Integer.toString(l)); + + f = 1.23f; + double d = f; // widen float to double + System.out.println("d=123 : " + (int)(d*100)); + + s = AssignmentConversionTest.sfi; + System.out.println("s=100 : " + s); + + s = 12+2; + System.out.println("s=12+2=" + (12+2) + ": "+ s); + + s = 12-2; + System.out.println("s=12-2=" + (12-2) + ": "+ s); + + s = 12*2; + System.out.println("s=12*2=" + (12*2) + ": "+ s); + + s = 12/2; + System.out.println("s=12/2=" + (12/2) + ": "+ s); + + s = 12%2; + System.out.println("s=12%2=" + (12%2) + ": "+ s); + + s = 12|2; + System.out.println("s=12|2=" + (12|2) + ": "+ s); + + s = 12^2; + System.out.println("s=12^2=" + (12^2) + ": "+ s); + + s = 12&2; + System.out.println("s=12&2=" + (12&2) + ": "+ s); + + s = 12>2?1:2; + System.out.println("s=12>2?1:2=" + (12>2?1:2) + ": "+ s); + + s = 12<2?1:2; + System.out.println("s=12<2?1:2=" + (12<2?1:2) + ": "+ s); + + /* + byte a = 12<2; + + s = 12%2?1:2; + System.out.println("s=12&2=" + (12%2?1:2) + ": "+ s); + + short se = 123; + char ce = se; // error: would require cast + se = ce; // error: would require cast + */ + } +}