checkField(cd,fd);
}
+ boolean hasConstructor = false;
for(Iterator method_it=cd.getMethods(); method_it.hasNext();) {
MethodDescriptor md=(MethodDescriptor)method_it.next();
checkMethod(cd,md);
+ hasConstructor |= md.isConstructor();
+ }
+ if(!hasConstructor) {
+ // add a default constructor for this class
+ MethodDescriptor md = new MethodDescriptor(new Modifiers(Modifiers.PUBLIC),
+ cd.getSymbol(), false);
+ BlockNode bn=new BlockNode();
+ state.addTreeCode(md,bn);
+ cd.addMethod(md);
+ checkMethod(cd,md);
}
}
}
}
}
/* Check return type */
- if (!md.isConstructor())
+ if (!md.isConstructor() && !md.isStaticBlock())
if (!md.getReturnType().isVoid())
checkTypeDescriptor(md.getReturnType());
case Kind.IfStatementNode:
checkIfStatementNode(md, nametable, (IfStatementNode)bsn);
return;
+
+ case Kind.SwitchStatementNode:
+ checkSwitchStatementNode(md, nametable, (SwitchStatementNode)bsn);
+ return;
case Kind.LoopNode:
checkLoopNode(md, nametable, (LoopNode)bsn);
if (isn.getFalseBlock()!=null)
checkBlockNode(md, nametable, isn.getFalseBlock());
}
+
+ void checkSwitchStatementNode(Descriptor md, SymbolTable nametable, SwitchStatementNode ssn) {
+ checkExpressionNode(md, nametable, ssn.getCondition(), new TypeDescriptor(TypeDescriptor.INT));
+
+ BlockNode sbn = ssn.getSwitchBody();
+ boolean hasdefault = false;
+ for(int i = 0; i < sbn.size(); i++) {
+ boolean containdefault = checkSwitchBlockNode(md, nametable, (SwitchBlockNode)sbn.get(i));
+ if(hasdefault && containdefault) {
+ throw new Error("Error: duplicate default branch in switch-case statement in Method: " + md.getSymbol());
+ }
+ hasdefault = containdefault;
+ }
+ }
+
+ boolean checkSwitchBlockNode(Descriptor md, SymbolTable nametable, SwitchBlockNode sbn) {
+ Vector<SwitchLabelNode> slnv = sbn.getSwitchConditions();
+ int defaultb = 0;
+ for(int i = 0; i < slnv.size(); i++) {
+ if(slnv.elementAt(i).isdefault) {
+ defaultb++;
+ } else {
+ checkConstantExpressionNode(md, nametable, slnv.elementAt(i).getCondition(), new TypeDescriptor(TypeDescriptor.INT));
+ }
+ }
+ if(defaultb > 1) {
+ throw new Error("Error: duplicate default branch in switch-case statement in Method: " + md.getSymbol());
+ } else {
+ checkBlockNode(md, nametable, sbn.getSwitchBlockStatement());
+ return (defaultb > 0);
+ }
+ }
+
+ void checkConstantExpressionNode(Descriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
+ switch(en.kind()) {
+ case Kind.FieldAccessNode:
+ checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td);
+ return;
+
+ case Kind.LiteralNode:
+ checkLiteralNode(md,nametable,(LiteralNode)en,td);
+ return;
+ }
+ throw new Error();
+ }
void checkExpressionNode(Descriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) {
switch(en.kind()) {
case Kind.ArrayInitializerNode:
checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en, td);
return;
+
+ case Kind.ClassTypeNode:
+ checkClassTypeNode(md, nametable, (ClassTypeNode) en, td);
+ return;
}
throw new Error();
}
+ void checkClassTypeNode(Descriptor md, SymbolTable nametable, ClassTypeNode tn, TypeDescriptor td) {
+ checkTypeDescriptor(tn.getType());
+ }
+
void checkCastNode(Descriptor md, SymbolTable nametable, CastNode cn, TypeDescriptor td) {
/* Get type descriptor */
if (cn.getType()==null) {
FieldDescriptor fd=null;
if (ltd.isArray()&&fieldname.equals("length"))
fd=FieldDescriptor.arrayLength;
- else
+ else
fd=(FieldDescriptor) ltd.getClassDesc().getFieldTable().get(fieldname);
if(state.MGC) {
// TODO add version for normal Java later
if(ltd.isStatic()) {
- // check if this field is a static field
- if(!fd.isStatic()) {
+ if(ltd.getClassDesc().isEnum()) {
+ int value = ltd.getClassDesc().getEnumConstant(fieldname);
+ if(-1 == value) {
+ // check if this field is an enum constant
+ throw new Error(fieldname + " is not an enum constant in "+fan.printNode(0)+" in "+md);
+ }
+ 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()) {
+ // 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);
}
}
}
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) {
cd = ((MethodDescriptor)md).getClassDesc();
SymbolTable fieldtbl = cd.getFieldTable();
FieldDescriptor fd=(FieldDescriptor)fieldtbl.get(varname);
- if((fd == null) || (!fd.isStatic()) || (!fd.isVolatile())){
- // no such field in the class or it is not a static field
- throw new Error("Name "+varname+" should not be used in static block: "+md);
+ if((fd == null) || (!fd.isStatic())){
+ // no such field in the class, check if this is a class
+ if(varname.equals("this")) {
+ throw new Error("Error: access this obj in a static block");
+ }
+ cd=getClass(varname);
+ if(cd != null) {
+ // this is a class name
+ nn.setClassDesc(cd);
+ return;
+ } else {
+ throw new Error("Name "+varname+" should not be used in static block: "+md);
+ }
} else {
// this is a static field
nn.setField(fd);
}
void checkArrayInitializerNode(Descriptor md, SymbolTable nametable, ArrayInitializerNode ain, TypeDescriptor td) {
+ Vector<TypeDescriptor> vec_type = new Vector<TypeDescriptor>();
for( int i = 0; i < ain.numVarInitializers(); ++i ) {
- checkExpressionNode(md, nametable, ain.getVarInitializer(i), td);
+ checkExpressionNode(md, nametable, ain.getVarInitializer(i), td==null?td:td.dereference());
+ vec_type.add(ain.getVarInitializer(i).getType());
}
+ // descide the type of this variableInitializerNode
+ TypeDescriptor out_type = vec_type.elementAt(0);
+ for(int i = 1; i < vec_type.size(); i++) {
+ TypeDescriptor tmp_type = vec_type.elementAt(i);
+ if(out_type == null) {
+ if(tmp_type != null) {
+ out_type = tmp_type;
+ }
+ } else if(out_type.isNull()) {
+ if(!tmp_type.isNull() ) {
+ if(!tmp_type.isArray()) {
+ throw new Error("Error: mixed type in var initializer list");
+ } else {
+ out_type = tmp_type;
+ }
+ }
+ } else if(out_type.isArray()) {
+ if(tmp_type.isArray()) {
+ if(tmp_type.getArrayCount() > out_type.getArrayCount()) {
+ out_type = tmp_type;
+ }
+ } else if((tmp_type != null) && (!tmp_type.isNull())) {
+ throw new Error("Error: mixed type in var initializer list");
+ }
+ } else if(out_type.isInt()) {
+ if(!tmp_type.isInt()) {
+ throw new Error("Error: mixed type in var initializer list");
+ }
+ } else if(out_type.isString()) {
+ if(!tmp_type.isString()) {
+ throw new Error("Error: mixed type in var initializer list");
+ }
+ }
+ }
+ if(out_type != null) {
+ out_type = out_type.makeArray(state);
+ }
+ ain.setType(out_type);
}
void checkAssignmentNode(Descriptor md, SymbolTable nametable, AssignmentNode an, TypeDescriptor td) {
}
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));
+ }
}
}
if (td!=null&&!typeutil.isSuperorType(td, typetolookin))
throw new Error(typetolookin + " isn't a "+td);
+
+ /* Check Array Initializers */
+ if(state.MGC && (con.getArrayInitializer() != null)) {
+ checkArrayInitializerNode(md, nametable, con.getArrayInitializer(), td);
+ }
/* Check flag effects */
if (con.getFlagEffects()!=null) {
ExpressionNode en=min.getArg(i);
checkExpressionNode(md,nametable,en,null);
tdarray[i]=en.getType();
+ if(state.MGC && en.getType().isClass() && en.getType().getClassDesc().isEnum()) {
+ tdarray[i] = new TypeDescriptor(TypeDescriptor.INT);
+ }
}
TypeDescriptor typetolookin=null;
if (min.getExpression()!=null) {