@@ -184,7 +184,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
/* Expands a simple class name to java.lang.*. | |||
* For example, this converts Object into java/lang/Object. | |||
*/ | |||
protected abstract String resolveClassName(String jvmClassName) | |||
protected abstract String resolveClassName(String jvmClassName, int lineNumber) | |||
throws CompileError; | |||
/** | |||
@@ -802,7 +802,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
@Override | |||
public void atDeclarator(Declarator d) throws CompileError { | |||
d.setLocalVar(getMaxLocals()); | |||
d.setClassName(resolveClassName(d.getClassName())); | |||
d.setClassName(resolveClassName(d.getClassName(), d.getLineNumber())); | |||
int size; | |||
if (is2word(d.getType(), d.getArrayDim())) | |||
@@ -1656,7 +1656,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
int i = cname.indexOf("[L"); | |||
if (i >= 0) { | |||
String name = cname.substring(i + 2, cname.length() - 1); | |||
String name2 = resolveClassName(name); | |||
String name2 = resolveClassName(name, expr.getLineNumber()); | |||
if (!name.equals(name2)) { | |||
/* For example, to obtain String[].class, | |||
* "[Ljava.lang.String;" (not "[Ljava/lang/String"!) | |||
@@ -1673,7 +1673,7 @@ public abstract class CodeGen extends Visitor implements Opcode, TokenId { | |||
} | |||
} | |||
else { | |||
cname = resolveClassName(MemberResolver.javaToJvmName(cname)); | |||
cname = resolveClassName(MemberResolver.javaToJvmName(cname), expr.getLineNumber()); | |||
cname = MemberResolver.jvmToJavaName(cname); | |||
} | |||
@@ -37,7 +37,7 @@ public class CompileError extends Exception { | |||
reason = String.format("line %d: %s", lineNumber, s); | |||
} | |||
public CompileError(String s) { | |||
private CompileError(String s) { | |||
reason = s; | |||
lex = null; | |||
} |
@@ -95,7 +95,8 @@ public class Javac { | |||
*/ | |||
public CtMember compile(String src) throws CompileError { | |||
int startLine = gen.thisClass.getLinesCount(); | |||
Parser p = new Parser(new Lex(src, startLine)); | |||
Lex lex = new Lex(src, startLine); | |||
Parser p = new Parser(lex); | |||
ASTList mem = p.parseMember1(stable); | |||
try { | |||
if (mem instanceof FieldDecl) | |||
@@ -107,11 +108,8 @@ public class Javac { | |||
decl.getClassFile2()); | |||
return cb; | |||
} | |||
catch (BadBytecode bb) { | |||
throw new CompileError(bb.getMessage()); | |||
} | |||
catch (CannotCompileException e) { | |||
throw new CompileError(e.getMessage()); | |||
catch (BadBytecode | CannotCompileException bb) { | |||
throw new CompileError(bb.getMessage(), lex.getLineNumber()); | |||
} | |||
} | |||
@@ -186,7 +184,7 @@ public class Javac { | |||
return method; | |||
} | |||
catch (NotFoundException e) { | |||
throw new CompileError(e.toString()); | |||
throw new CompileError(e.toString(), md.getLineNumber()); | |||
} | |||
} | |||
@@ -222,7 +220,7 @@ public class Javac { | |||
Stmnt s = p.parseStatement(stb); | |||
if (p.hasMore()) | |||
throw new CompileError( | |||
"the method/constructor body must be surrounded by {}"); | |||
"the method/constructor body must be surrounded by {}", s.getLineNumber()); | |||
boolean callSuper = false; | |||
if (method instanceof CtConstructor) | |||
@@ -234,7 +232,7 @@ public class Javac { | |||
return bytecode; | |||
} | |||
catch (NotFoundException e) { | |||
throw new CompileError(e.toString()); | |||
throw new CompileError(e.toString(), -1); | |||
} | |||
} | |||
@@ -446,7 +444,7 @@ public class Javac { | |||
ProceedHandler h = new ProceedHandler() { | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode b, ASTList args) | |||
public void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
ASTree expr = new Member(m, texpr.getLineNumber()); | |||
@@ -459,7 +457,7 @@ public class Javac { | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker check, ASTList args) | |||
public void setReturnType(JvstTypeChecker check, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
ASTree expr = new Member(m, texpr.getLineNumber()); | |||
@@ -492,7 +490,7 @@ public class Javac { | |||
ProceedHandler h = new ProceedHandler() { | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode b, ASTList args) | |||
public void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
Expr expr = Expr.make(TokenId.MEMBER, | |||
@@ -503,7 +501,7 @@ public class Javac { | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker check, ASTList args) | |||
public void setReturnType(JvstTypeChecker check, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
Expr expr = Expr.make(TokenId.MEMBER, | |||
@@ -538,14 +536,14 @@ public class Javac { | |||
ProceedHandler h = new ProceedHandler() { | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode b, ASTList args) | |||
public void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
gen.compileInvokeSpecial(texpr, methodIndex, descriptor, args); | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker c, ASTList args) | |||
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
c.compileInvokeSpecial(texpr, classname, methodname, descriptor, args); |
@@ -147,7 +147,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
if (arrayDim != 1 || exprType != CLASS) | |||
throw new CompileError("invalid type for " + paramArrayName, expr.getLineNumber()); | |||
atAssignParamList(paramTypeList, bytecode); | |||
atAssignParamList(paramTypeList, bytecode, expr.getLineNumber()); | |||
if (!doDup) | |||
bytecode.addOpcode(POP); | |||
} | |||
@@ -155,7 +155,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
super.atFieldAssign(expr, op, left, right, doDup); | |||
} | |||
protected void atAssignParamList(CtClass[] params, Bytecode code) | |||
protected void atAssignParamList(CtClass[] params, Bytecode code, int lineNumber) | |||
throws CompileError | |||
{ | |||
if (params == null) | |||
@@ -167,7 +167,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
code.addOpcode(DUP); | |||
code.addIconst(i); | |||
code.addOpcode(AALOAD); | |||
compileUnwrapValue(params[i], code); | |||
compileUnwrapValue(params[i], code, lineNumber); | |||
code.addStore(varNo, params[i]); | |||
varNo += is2word(exprType, arrayDim) ? 2 : 1; | |||
} | |||
@@ -201,10 +201,10 @@ public class JvstCodeGen extends MemberCodeGen { | |||
protected void atCastToRtype(CastExpr expr) throws CompileError { | |||
expr.getOprand().accept(this); | |||
if (exprType == VOID || isRefType(exprType) || arrayDim > 0) | |||
compileUnwrapValue(returnType, bytecode); | |||
compileUnwrapValue(returnType, bytecode, expr.getLineNumber()); | |||
else if (returnType instanceof CtPrimitiveType) { | |||
CtPrimitiveType pt = (CtPrimitiveType)returnType; | |||
int destType = MemberResolver.descToType(pt.getDescriptor()); | |||
int destType = MemberResolver.descToType(pt.getDescriptor(), expr.getLineNumber()); | |||
atNumCastExpr(exprType, destType); | |||
exprType = destType; | |||
arrayDim = 0; | |||
@@ -219,7 +219,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
if (isRefType(exprType) || arrayDim > 0) | |||
return; // Object type. do nothing. | |||
CtClass clazz = resolver.lookupClass(exprType, arrayDim, className); | |||
CtClass clazz = resolver.lookupClass(exprType, arrayDim, className, expr.getLineNumber()); | |||
if (clazz instanceof CtPrimitiveType) { | |||
CtPrimitiveType pt = (CtPrimitiveType)clazz; | |||
String wrapper = pt.getWrapperName(); | |||
@@ -249,7 +249,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
if (method instanceof Member) { | |||
String name = ((Member)method).get(); | |||
if (procHandler != null && name.equals(proceedName)) { | |||
procHandler.doit(this, bytecode, (ASTList)expr.oprand2()); | |||
procHandler.doit(this, bytecode, (ASTList)expr.oprand2(), expr.getLineNumber()); | |||
return; | |||
} | |||
else if (name.equals(cflowName)) { | |||
@@ -364,7 +364,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
for (int k = 0; k < n; ++k) { | |||
CtClass p = params[k]; | |||
regno += bytecode.addLoad(regno, p); | |||
setType(p); | |||
setType(p, a.getLineNumber()); | |||
types[i] = exprType; | |||
dims[i] = arrayDim; | |||
cnames[i] = className; | |||
@@ -420,7 +420,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
atMethodArgs(args, new int[nargs], new int[nargs], | |||
new String[nargs]); | |||
bytecode.addInvokespecial(methodIndex, descriptor); | |||
setReturnType(descriptor, false, false); | |||
setReturnType(descriptor, false, false, target.getLineNumber()); | |||
addNullIfVoid(); | |||
} | |||
@@ -569,7 +569,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
className = jvmJavaLangObject; | |||
} | |||
else | |||
setType(cc); | |||
setType(cc, cc.getLinesCount()); | |||
Declarator decl | |||
= new Declarator(exprType, className, arrayDim, | |||
@@ -593,7 +593,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
while ((c = typeDesc.charAt(dim)) == '[') | |||
++dim; | |||
int type = MemberResolver.descToType(c); | |||
int type = MemberResolver.descToType(c, -1); | |||
String cname = null; | |||
if (type == CLASS) { | |||
if (dim == 0) | |||
@@ -653,7 +653,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
return 8; | |||
} | |||
protected void compileUnwrapValue(CtClass type, Bytecode code) | |||
protected void compileUnwrapValue(CtClass type, Bytecode code, int lineNumber) | |||
throws CompileError | |||
{ | |||
if (type == CtClass.voidType) { | |||
@@ -662,7 +662,7 @@ public class JvstCodeGen extends MemberCodeGen { | |||
} | |||
if (exprType == VOID) | |||
throw new CompileError("invalid type for " + returnCastName); | |||
throw new CompileError("invalid type for " + returnCastName, lineNumber); | |||
if (type instanceof CtPrimitiveType) { | |||
CtPrimitiveType pt = (CtPrimitiveType)type; | |||
@@ -671,34 +671,34 @@ public class JvstCodeGen extends MemberCodeGen { | |||
code.addCheckcast(wrapper); | |||
code.addInvokevirtual(wrapper, pt.getGetMethodName(), | |||
pt.getGetMethodDescriptor()); | |||
setType(type); | |||
setType(type, lineNumber); | |||
} | |||
else { | |||
code.addCheckcast(type); | |||
setType(type); | |||
setType(type, lineNumber); | |||
} | |||
} | |||
/* Sets exprType, arrayDim, and className; | |||
* If type is void, then this method does nothing. | |||
*/ | |||
public void setType(CtClass type) throws CompileError { | |||
setType(type, 0); | |||
public void setType(CtClass type, int lineNumber) throws CompileError { | |||
setType(type, 0, lineNumber); | |||
} | |||
private void setType(CtClass type, int dim) throws CompileError { | |||
private void setType(CtClass type, int dim, int lineNumber) throws CompileError { | |||
if (type.isPrimitive()) { | |||
CtPrimitiveType pt = (CtPrimitiveType)type; | |||
exprType = MemberResolver.descToType(pt.getDescriptor()); | |||
exprType = MemberResolver.descToType(pt.getDescriptor(), lineNumber); | |||
arrayDim = dim; | |||
className = null; | |||
} | |||
else if (type.isArray()) | |||
try { | |||
setType(type.getComponentType(), dim + 1); | |||
setType(type.getComponentType(), dim + 1, lineNumber); | |||
} | |||
catch (NotFoundException e) { | |||
throw new CompileError("undefined type: " + type.getName()); | |||
throw new CompileError("undefined type: " + type.getName(), lineNumber); | |||
} | |||
else { | |||
exprType = CLASS; | |||
@@ -714,9 +714,9 @@ public class JvstCodeGen extends MemberCodeGen { | |||
if (type instanceof CtPrimitiveType) { | |||
CtPrimitiveType pt = (CtPrimitiveType)type; | |||
atNumCastExpr(exprType, | |||
MemberResolver.descToType(pt.getDescriptor())); | |||
MemberResolver.descToType(pt.getDescriptor(), type.getLinesCount() - 1)); | |||
} | |||
else | |||
throw new CompileError("type mismatch"); | |||
throw new CompileError("type mismatch", type.getLinesCount() - 1); | |||
} | |||
} |
@@ -127,7 +127,7 @@ public class JvstTypeChecker extends TypeChecker { | |||
compileUnwrapValue(returnType, expr.getLineNumber()); | |||
else if (returnType instanceof CtPrimitiveType) { | |||
CtPrimitiveType pt = (CtPrimitiveType)returnType; | |||
int destType = MemberResolver.descToType(pt.getDescriptor()); | |||
int destType = MemberResolver.descToType(pt.getDescriptor(), expr.getLineNumber()); | |||
exprType = destType; | |||
arrayDim = 0; | |||
className = null; | |||
@@ -139,7 +139,7 @@ public class JvstTypeChecker extends TypeChecker { | |||
if (CodeGen.isRefType(exprType) || arrayDim > 0) | |||
return; // Object type. do nothing. | |||
CtClass clazz = resolver.lookupClass(exprType, arrayDim, className); | |||
CtClass clazz = resolver.lookupClass(exprType, arrayDim, className, expr.getLineNumber()); | |||
if (clazz instanceof CtPrimitiveType) { | |||
exprType = CLASS; | |||
arrayDim = 0; | |||
@@ -158,7 +158,7 @@ public class JvstTypeChecker extends TypeChecker { | |||
if (codeGen.procHandler != null | |||
&& name.equals(codeGen.proceedName)) { | |||
codeGen.procHandler.setReturnType(this, | |||
(ASTList)expr.oprand2()); | |||
(ASTList)expr.oprand2(), expr.getLineNumber()); | |||
return; | |||
} | |||
else if (name.equals(JvstCodeGen.cflowName)) { | |||
@@ -223,7 +223,7 @@ public class JvstTypeChecker extends TypeChecker { | |||
int n = params.length; | |||
for (int k = 0; k < n; ++k) { | |||
CtClass p = params[k]; | |||
setType(p); | |||
setType(p, a.getLineNumber()); | |||
types[i] = exprType; | |||
dims[i] = arrayDim; | |||
cnames[i] = className; | |||
@@ -254,7 +254,7 @@ public class JvstTypeChecker extends TypeChecker { | |||
int nargs = getMethodArgsLength(args); | |||
atMethodArgs(args, new int[nargs], new int[nargs], | |||
new String[nargs]); | |||
setReturnType(descriptor); | |||
setReturnType(descriptor, target.getLineNumber()); | |||
addNullIfVoid(); | |||
} | |||
@@ -263,29 +263,29 @@ public class JvstTypeChecker extends TypeChecker { | |||
if (type == CtClass.voidType) | |||
addNullIfVoid(); | |||
else | |||
setType(type); | |||
setType(type, lineNumber); | |||
} | |||
/* Sets exprType, arrayDim, and className; | |||
* If type is void, then this method does nothing. | |||
*/ | |||
public void setType(CtClass type) throws CompileError { | |||
setType(type, 0); | |||
public void setType(CtClass type, int lineNumber) throws CompileError { | |||
setType(type, 0, lineNumber); | |||
} | |||
private void setType(CtClass type, int dim) throws CompileError { | |||
private void setType(CtClass type, int dim, int lineNumber) throws CompileError { | |||
if (type.isPrimitive()) { | |||
CtPrimitiveType pt = (CtPrimitiveType)type; | |||
exprType = MemberResolver.descToType(pt.getDescriptor()); | |||
exprType = MemberResolver.descToType(pt.getDescriptor(), lineNumber); | |||
arrayDim = dim; | |||
className = null; | |||
} | |||
else if (type.isArray()) | |||
try { | |||
setType(type.getComponentType(), dim + 1); | |||
setType(type.getComponentType(), dim + 1, lineNumber); | |||
} | |||
catch (NotFoundException e) { | |||
throw new CompileError("undefined type: " + type.getName()); | |||
throw new CompileError("undefined type: " + type.getName(), lineNumber); | |||
} | |||
else { | |||
exprType = CLASS; |
@@ -254,7 +254,7 @@ public class MemberCodeGen extends CodeGen { | |||
decl.setLocalVar(var); | |||
CtClass type = resolver.lookupClassByJvmName(decl.getClassName()); | |||
CtClass type = resolver.lookupClassByJvmName(decl.getClassName(), st.getLineNumber()); | |||
decl.setClassName(MemberResolver.javaToJvmName(type.getName())); | |||
bc.addExceptionHandler(start, end, bc.currentPc(), type); | |||
bc.growStack(1); | |||
@@ -373,7 +373,7 @@ public class MemberCodeGen extends CodeGen { | |||
String elementClass; | |||
if (type == CLASS) { | |||
elementClass = resolveClassName(jvmClassname); | |||
elementClass = resolveClassName(jvmClassname, lineNumber); | |||
bytecode.addAnewarray(MemberResolver.jvmToJavaName(elementClass)); | |||
} | |||
else { | |||
@@ -515,7 +515,7 @@ public class MemberCodeGen extends CodeGen { | |||
int op = e.getOperator(); | |||
if (op == MEMBER) { // static method | |||
targetClass | |||
= resolver.lookupClass(((Symbol)e.oprand1()).get(), false); | |||
= resolver.lookupClass(((Symbol)e.oprand1()).get(), false, expr.getLineNumber()); | |||
isStatic = true; | |||
} | |||
else if (op == '.') { | |||
@@ -552,15 +552,15 @@ public class MemberCodeGen extends CodeGen { | |||
} | |||
if (arrayDim > 0) | |||
targetClass = resolver.lookupClass(javaLangObject, true); | |||
targetClass = resolver.lookupClass(javaLangObject, true, expr.getLineNumber()); | |||
else if (exprType == CLASS /* && arrayDim == 0 */) | |||
targetClass = resolver.lookupClassByJvmName(className); | |||
targetClass = resolver.lookupClassByJvmName(className, expr.getLineNumber()); | |||
else | |||
badMethod(); | |||
badMethod(e.getLineNumber()); | |||
} | |||
} | |||
else | |||
badMethod(); | |||
badMethod(expr.getLineNumber()); | |||
} | |||
else | |||
fatal(expr.getLineNumber()); | |||
@@ -569,8 +569,8 @@ public class MemberCodeGen extends CodeGen { | |||
aload0pos, cached); | |||
} | |||
private static void badMethod() throws CompileError { | |||
throw new CompileError("bad method"); | |||
private static void badMethod(int lineNumber) throws CompileError { | |||
throw new CompileError("bad method", lineNumber); | |||
} | |||
/* | |||
@@ -645,7 +645,7 @@ public class MemberCodeGen extends CodeGen { | |||
if (mname.equals(MethodInfo.nameInit)) { | |||
isSpecial = true; | |||
if (declClass != targetClass) | |||
throw new CompileError("no such constructor: " + targetClass.getName()); | |||
throw new CompileError("no such constructor: " + targetClass.getName(), targetClass.getLinesCount() - 1); | |||
if (declClass != thisClass && AccessFlag.isPrivate(acc)) { | |||
if (declClass.getClassFile().getMajorVersion() < ClassFile.JAVA_8 | |||
@@ -701,12 +701,12 @@ public class MemberCodeGen extends CodeGen { | |||
} | |||
else | |||
if (isStatic) | |||
throw new CompileError(mname + " is not static"); | |||
throw new CompileError(mname + " is not static", targetClass.getLinesCount() - 1); | |||
else | |||
bytecode.addInvokevirtual(declClass, mname, desc); | |||
} | |||
setReturnType(desc, isStatic, popTarget); | |||
setReturnType(desc, isStatic, popTarget, targetClass.getLinesCount() - 1); | |||
} | |||
/* | |||
@@ -729,7 +729,7 @@ public class MemberCodeGen extends CodeGen { | |||
} | |||
throw new CompileError("Method " + methodName | |||
+ " is private"); | |||
+ " is private", declClass.getLinesCount() - 1); | |||
} | |||
/* | |||
@@ -752,7 +752,7 @@ public class MemberCodeGen extends CodeGen { | |||
} | |||
throw new CompileError("the called constructor is private in " | |||
+ declClass.getName()); | |||
+ declClass.getName(), declClass.getLinesCount() - 1); | |||
} | |||
private boolean isEnclosing(CtClass outer, CtClass inner) { | |||
@@ -785,12 +785,12 @@ public class MemberCodeGen extends CodeGen { | |||
} | |||
} | |||
void setReturnType(String desc, boolean isStatic, boolean popTarget) | |||
void setReturnType(String desc, boolean isStatic, boolean popTarget, int lineNumber) | |||
throws CompileError | |||
{ | |||
int i = desc.indexOf(')'); | |||
if (i < 0) | |||
badMethod(); | |||
badMethod(lineNumber); | |||
char c = desc.charAt(++i); | |||
int dim = 0; | |||
@@ -803,13 +803,13 @@ public class MemberCodeGen extends CodeGen { | |||
if (c == 'L') { | |||
int j = desc.indexOf(';', i + 1); | |||
if (j < 0) | |||
badMethod(); | |||
badMethod(lineNumber); | |||
exprType = CLASS; | |||
className = desc.substring(i + 1, j); | |||
} | |||
else { | |||
exprType = MemberResolver.descToType(c); | |||
exprType = MemberResolver.descToType(c, lineNumber); | |||
className = null; | |||
} | |||
@@ -843,7 +843,7 @@ public class MemberCodeGen extends CodeGen { | |||
int fi; | |||
if (op == '=') { | |||
FieldInfo finfo = f.getFieldInfo2(); | |||
setFieldType(finfo); | |||
setFieldType(finfo, expr.getLineNumber()); | |||
AccessorMaker maker = isAccessibleField(f, finfo, expr.getLineNumber()); | |||
if (maker == null) | |||
fi = addFieldrefInfo(f, finfo); | |||
@@ -926,7 +926,7 @@ public class MemberCodeGen extends CodeGen { | |||
atFieldRead(f, is_static,expr.getLineNumber() ); | |||
else { | |||
cexpr.accept(this); | |||
setFieldType(f.getFieldInfo2()); | |||
setFieldType(f.getFieldInfo2(), expr.getLineNumber()); | |||
} | |||
} | |||
@@ -946,7 +946,7 @@ public class MemberCodeGen extends CodeGen { | |||
*/ | |||
private int atFieldRead(CtField f, boolean isStatic, int lineNumber) throws CompileError { | |||
FieldInfo finfo = f.getFieldInfo2(); | |||
boolean is2byte = setFieldType(finfo); | |||
boolean is2byte = setFieldType(finfo, lineNumber); | |||
AccessorMaker maker = isAccessibleField(f, finfo, lineNumber); | |||
if (maker != null) { | |||
MethodInfo minfo = maker.getFieldGetter(finfo, isStatic); | |||
@@ -996,7 +996,7 @@ public class MemberCodeGen extends CodeGen { | |||
* | |||
* @return true if the field type is long or double. | |||
*/ | |||
private boolean setFieldType(FieldInfo finfo) throws CompileError { | |||
private boolean setFieldType(FieldInfo finfo, int lineNumber) throws CompileError { | |||
String type = finfo.getDescriptor(); | |||
int i = 0; | |||
@@ -1008,7 +1008,7 @@ public class MemberCodeGen extends CodeGen { | |||
} | |||
arrayDim = dim; | |||
exprType = MemberResolver.descToType(c); | |||
exprType = MemberResolver.descToType(c, lineNumber); | |||
if (c == 'L') | |||
className = type.substring(i + 1, type.indexOf(';', i + 1)); | |||
@@ -1201,7 +1201,7 @@ public class MemberCodeGen extends CodeGen { | |||
* For example, this converts Object into java/lang/Object. | |||
*/ | |||
@Override | |||
protected String resolveClassName(String jvmName) throws CompileError { | |||
return resolver.resolveJvmClassName(jvmName); | |||
protected String resolveClassName(String jvmName, int lineNumber) throws CompileError { | |||
return resolver.resolveJvmClassName(jvmName, lineNumber); | |||
} | |||
} |
@@ -50,8 +50,8 @@ public class MemberResolver implements TokenId { | |||
public ClassPool getClassPool() { return classPool; } | |||
private static void fatal() throws CompileError { | |||
throw new CompileError("fatal"); | |||
private static void fatal(int lineNumber) throws CompileError { | |||
throw new CompileError("fatal", lineNumber); | |||
} | |||
public static class Method { | |||
@@ -85,7 +85,7 @@ public class MemberResolver implements TokenId { | |||
if (current != null && clazz == currentClass) | |||
if (current.getName().equals(methodName)) { | |||
int res = compareSignature(current.getDescriptor(), | |||
argTypes, argDims, argClassNames); | |||
argTypes, argDims, argClassNames, currentClass.getLinesCount() - 1); | |||
if (res != NO) { | |||
Method r = new Method(clazz, current, res); | |||
if (res == YES) | |||
@@ -116,7 +116,7 @@ public class MemberResolver implements TokenId { | |||
if (minfo.getName().equals(methodName) | |||
&& (minfo.getAccessFlags() & AccessFlag.BRIDGE) == 0) { | |||
int res = compareSignature(minfo.getDescriptor(), | |||
argTypes, argDims, argClassNames); | |||
argTypes, argDims, argClassNames, clazz.getLinesCount() - 1); | |||
if (res != NO) { | |||
Method r = new Method(clazz, minfo, res); | |||
if (res == YES) | |||
@@ -192,7 +192,7 @@ public class MemberResolver implements TokenId { | |||
* of parameter types that do not exactly match. | |||
*/ | |||
private int compareSignature(String desc, int[] argTypes, | |||
int[] argDims, String[] argClassNames) | |||
int[] argDims, String[] argClassNames, int lineNumber) | |||
throws CompileError | |||
{ | |||
int result = YES; | |||
@@ -240,9 +240,9 @@ public class MemberResolver implements TokenId { | |||
String cname = desc.substring(i, j); | |||
if (!cname.equals(argClassNames[n])) { | |||
CtClass clazz = lookupClassByJvmName(argClassNames[n]); | |||
CtClass clazz = lookupClassByJvmName(argClassNames[n], lineNumber); | |||
try { | |||
if (clazz.subtypeOf(lookupClassByJvmName(cname))) | |||
if (clazz.subtypeOf(lookupClassByJvmName(cname, lineNumber))) | |||
result++; | |||
else | |||
return NO; | |||
@@ -255,7 +255,7 @@ public class MemberResolver implements TokenId { | |||
i = j + 1; | |||
} | |||
else { | |||
int t = descToType(c); | |||
int t = descToType(c, lineNumber); | |||
int at = argTypes[n]; | |||
if (t != at) | |||
if (t == INT | |||
@@ -273,7 +273,7 @@ public class MemberResolver implements TokenId { | |||
* Only used by fieldAccess() in MemberCodeGen and TypeChecker. | |||
* | |||
* @param jvmClassName a JVM class name. e.g. java/lang/String | |||
* @see #lookupClass(String, boolean) | |||
* @see #lookupClass(String, boolean, int) | |||
*/ | |||
public CtField lookupFieldByJvmName2(String jvmClassName, Symbol fieldSym, | |||
ASTree expr) throws NoFieldException | |||
@@ -281,7 +281,7 @@ public class MemberResolver implements TokenId { | |||
String field = fieldSym.get(); | |||
CtClass cc = null; | |||
try { | |||
cc = lookupClass(jvmToJavaName(jvmClassName), true); | |||
cc = lookupClass(jvmToJavaName(jvmClassName), true, expr.getLineNumber()); | |||
} | |||
catch (CompileError e) { | |||
// EXPR might be part of a qualified class name. | |||
@@ -313,55 +313,56 @@ public class MemberResolver implements TokenId { | |||
public CtField lookupField(String className, Symbol fieldName) | |||
throws CompileError | |||
{ | |||
CtClass cc = lookupClass(className, false); | |||
CtClass cc = lookupClass(className, false, fieldName.getLineNumber()); | |||
try { | |||
return cc.getField(fieldName.get()); | |||
} | |||
catch (NotFoundException e) {} | |||
throw new CompileError("no such field: " + fieldName.get()); | |||
throw new CompileError("no such field: " + fieldName.get(), fieldName.getLineNumber()); | |||
} | |||
public CtClass lookupClassByName(ASTList name) throws CompileError { | |||
return lookupClass(Declarator.astToClassName(name, '.'), false); | |||
return lookupClass(Declarator.astToClassName(name, '.'), false, name.getLineNumber()); | |||
} | |||
public CtClass lookupClassByJvmName(String jvmName) throws CompileError { | |||
return lookupClass(jvmToJavaName(jvmName), false); | |||
public CtClass lookupClassByJvmName(String jvmName, int lineNumber) throws CompileError { | |||
return lookupClass(jvmToJavaName(jvmName), false, lineNumber); | |||
} | |||
public CtClass lookupClass(Declarator decl) throws CompileError { | |||
return lookupClass(decl.getType(), decl.getArrayDim(), | |||
decl.getClassName()); | |||
decl.getClassName(), decl.getLineNumber()); | |||
} | |||
/** | |||
* @param classname jvm class name. | |||
* @param classname jvm class name. | |||
* @param lineNumber | |||
*/ | |||
public CtClass lookupClass(int type, int dim, String classname) | |||
public CtClass lookupClass(int type, int dim, String classname, int lineNumber) | |||
throws CompileError | |||
{ | |||
String cname = ""; | |||
CtClass clazz; | |||
if (type == CLASS) { | |||
clazz = lookupClassByJvmName(classname); | |||
clazz = lookupClassByJvmName(classname, lineNumber); | |||
if (dim > 0) | |||
cname = clazz.getName(); | |||
else | |||
return clazz; | |||
} | |||
else | |||
cname = getTypeName(type); | |||
cname = getTypeName(type, lineNumber); | |||
while (dim-- > 0) | |||
cname += "[]"; | |||
return lookupClass(cname, false); | |||
return lookupClass(cname, false, lineNumber); | |||
} | |||
/* | |||
* type cannot be CLASS | |||
*/ | |||
static String getTypeName(int type) throws CompileError { | |||
static String getTypeName(int type, int lineNumber) throws CompileError { | |||
String cname = ""; | |||
switch (type) { | |||
case BOOLEAN : | |||
@@ -392,22 +393,23 @@ public class MemberResolver implements TokenId { | |||
cname = "void"; | |||
break; | |||
default : | |||
fatal(); | |||
fatal(lineNumber); | |||
} | |||
return cname; | |||
} | |||
/** | |||
* @param name a qualified class name. e.g. java.lang.String | |||
* @param name a qualified class name. e.g. java.lang.String | |||
* @param lineNumber | |||
*/ | |||
public CtClass lookupClass(String name, boolean notCheckInner) | |||
public CtClass lookupClass(String name, boolean notCheckInner, int lineNumber) | |||
throws CompileError | |||
{ | |||
Map<String,String> cache = getInvalidNames(); | |||
String found = cache.get(name); | |||
if (found == INVALID) | |||
throw new CompileError("no such class: " + name); | |||
throw new CompileError("no such class: " + name, lineNumber); | |||
else if (found != null) | |||
try { | |||
return classPool.get(found); | |||
@@ -419,7 +421,7 @@ public class MemberResolver implements TokenId { | |||
cc = lookupClass0(name, notCheckInner); | |||
} | |||
catch (NotFoundException e) { | |||
cc = searchImports(name); | |||
cc = searchImports(name, lineNumber); | |||
} | |||
cache.put(name, cc.getName()); | |||
@@ -454,7 +456,7 @@ public class MemberResolver implements TokenId { | |||
return ht; | |||
} | |||
private CtClass searchImports(String orgName) | |||
private CtClass searchImports(String orgName, int lineNumber) | |||
throws CompileError | |||
{ | |||
if (orgName.indexOf('.') < 0) { | |||
@@ -476,7 +478,7 @@ public class MemberResolver implements TokenId { | |||
} | |||
getInvalidNames().put(orgName, INVALID); | |||
throw new CompileError("no such class: " + orgName); | |||
throw new CompileError("no such class: " + orgName, lineNumber); | |||
} | |||
private CtClass lookupClass0(String classname, boolean notCheckInner) | |||
@@ -513,10 +515,10 @@ public class MemberResolver implements TokenId { | |||
/* Expands a simple class name to java.lang.*. | |||
* For example, this converts Object into java/lang/Object. | |||
*/ | |||
public String resolveJvmClassName(String jvmName) throws CompileError { | |||
public String resolveJvmClassName(String jvmName, int lineNumber) throws CompileError { | |||
if (jvmName == null) | |||
return null; | |||
return javaToJvmName(lookupClassByJvmName(jvmName).getName()); | |||
return javaToJvmName(lookupClassByJvmName(jvmName, lineNumber).getName()); | |||
} | |||
public static CtClass getSuperclass(CtClass c) throws CompileError { | |||
@@ -527,7 +529,7 @@ public class MemberResolver implements TokenId { | |||
} | |||
catch (NotFoundException e) {} | |||
throw new CompileError("cannot find the super class of " | |||
+ c.getName()); | |||
+ c.getName(), c.getLinesCount() - 1); | |||
} | |||
public static CtClass getSuperInterface(CtClass c, String interfaceName) | |||
@@ -540,7 +542,7 @@ public class MemberResolver implements TokenId { | |||
return intfs[i]; | |||
} catch (NotFoundException e) {} | |||
throw new CompileError("cannot find the super interface " + interfaceName | |||
+ " of " + c.getName()); | |||
+ " of " + c.getName(), c.getLinesCount() - 1); | |||
} | |||
public static String javaToJvmName(String classname) { | |||
@@ -551,7 +553,7 @@ public class MemberResolver implements TokenId { | |||
return classname.replace('/', '.'); | |||
} | |||
public static int descToType(char c) throws CompileError { | |||
public static int descToType(char c, int lineNumber) throws CompileError { | |||
switch (c) { | |||
case 'Z' : | |||
return BOOLEAN; | |||
@@ -575,7 +577,7 @@ public class MemberResolver implements TokenId { | |||
case '[' : | |||
return CLASS; | |||
default : | |||
fatal(); | |||
fatal(lineNumber); | |||
return VOID; // never reach here | |||
} | |||
} |
@@ -25,6 +25,6 @@ import javassist.compiler.ast.ASTList; | |||
* @see javassist.compiler.JvstCodeGen#setProceedHandler(ProceedHandler, String) | |||
*/ | |||
public interface ProceedHandler { | |||
void doit(JvstCodeGen gen, Bytecode b, ASTList args) throws CompileError; | |||
void setReturnType(JvstTypeChecker c, ASTList args) throws CompileError; | |||
void doit(JvstCodeGen gen, Bytecode b, ASTList args, int lineNumber) throws CompileError; | |||
void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber) throws CompileError; | |||
} |
@@ -73,14 +73,14 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
* into a String object. | |||
*/ | |||
protected static String argTypesToString(int[] types, int[] dims, | |||
String[] cnames) { | |||
String[] cnames, int lineNumber) { | |||
StringBuilder sbuf = new StringBuilder(); | |||
sbuf.append('('); | |||
int n = types.length; | |||
if (n > 0) { | |||
int i = 0; | |||
while (true) { | |||
typeToString(sbuf, types[i], dims[i], cnames[i]); | |||
typeToString(sbuf, types[i], dims[i], cnames[i], lineNumber); | |||
if (++i < n) | |||
sbuf.append(','); | |||
else | |||
@@ -97,7 +97,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
* into a String object. | |||
*/ | |||
protected static StringBuilder typeToString(StringBuilder sbuf, | |||
int type, int dim, String cname) { | |||
int type, int dim, String cname, int lineNumber) { | |||
String s; | |||
if (type == CLASS) | |||
s = MemberResolver.jvmToJavaName(cname); | |||
@@ -105,7 +105,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
s = "Object"; | |||
else | |||
try { | |||
s = MemberResolver.getTypeName(type); | |||
s = MemberResolver.getTypeName(type, lineNumber); | |||
} | |||
catch (CompileError e) { | |||
s = "?"; | |||
@@ -156,8 +156,8 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
/* Expands a simple class name to java.lang.*. | |||
* For example, this converts Object into java/lang/Object. | |||
*/ | |||
protected String resolveClassName(String jvmName) throws CompileError { | |||
return resolver.resolveJvmClassName(jvmName); | |||
protected String resolveClassName(String jvmName, int lineNumber) throws CompileError { | |||
return resolver.resolveJvmClassName(jvmName, lineNumber); | |||
} | |||
@Override | |||
@@ -168,7 +168,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
CtClass clazz = resolver.lookupClassByName(expr.getClassName()); | |||
String cname = clazz.getName(); | |||
ASTList args = expr.getArguments(); | |||
atMethodCallCore(clazz, MethodInfo.nameInit, args); | |||
atMethodCallCore(clazz, MethodInfo.nameInit, args, expr.getLineNumber()); | |||
exprType = CLASS; | |||
arrayDim = 0; | |||
className = MemberResolver.javaToJvmName(cname); | |||
@@ -294,7 +294,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
throws CompileError | |||
{ | |||
CtField f = fieldAccess(left); | |||
atFieldRead(f); | |||
atFieldRead(f, expr.getLineNumber()); | |||
int fType = exprType; | |||
int fDim = arrayDim; | |||
String cname = className; | |||
@@ -682,7 +682,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
if (op == MEMBER) // static method | |||
targetClass | |||
= resolver.lookupClass(((Symbol)e.oprand1()).get(), | |||
false); | |||
false, e.getLineNumber()); | |||
else if (op == '.') { | |||
ASTree target = e.oprand1(); | |||
String classFollowedByDotSuper = isDotSuper(target); | |||
@@ -707,26 +707,26 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
} | |||
if (arrayDim > 0) | |||
targetClass = resolver.lookupClass(javaLangObject, true); | |||
targetClass = resolver.lookupClass(javaLangObject, true, e.getLineNumber()); | |||
else if (exprType == CLASS /* && arrayDim == 0 */) | |||
targetClass = resolver.lookupClassByJvmName(className); | |||
targetClass = resolver.lookupClassByJvmName(className, e.getLineNumber()); | |||
else | |||
badMethod(); | |||
badMethod(e.getLineNumber()); | |||
} | |||
} | |||
else | |||
badMethod(); | |||
badMethod(expr.getLineNumber()); | |||
} | |||
else | |||
fatal(expr.getLineNumber()); | |||
MemberResolver.Method minfo | |||
= atMethodCallCore(targetClass, mname, args); | |||
= atMethodCallCore(targetClass, mname, args, expr.getLineNumber()); | |||
expr.setMethod(minfo); | |||
} | |||
private static void badMethod() throws CompileError { | |||
throw new CompileError("bad method"); | |||
private static void badMethod(int lineNumber) throws CompileError { | |||
throw new CompileError("bad method", lineNumber); | |||
} | |||
/** | |||
@@ -754,7 +754,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
* and the MethodInfo of that method. Never null. | |||
*/ | |||
public MemberResolver.Method atMethodCallCore(CtClass targetClass, | |||
String mname, ASTList args) | |||
String mname, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
int nargs = getMethodArgsLength(args); | |||
@@ -768,18 +768,18 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
mname, types, dims, cnames); | |||
if (found == null) { | |||
String clazz = targetClass.getName(); | |||
String signature = argTypesToString(types, dims, cnames); | |||
String signature = argTypesToString(types, dims, cnames, lineNumber); | |||
String msg; | |||
if (mname.equals(MethodInfo.nameInit)) | |||
msg = "cannot find constructor " + clazz + signature; | |||
else | |||
msg = mname + signature + " not found in " + clazz; | |||
throw new CompileError(msg); | |||
throw new CompileError(msg, lineNumber); | |||
} | |||
String desc = found.info.getDescriptor(); | |||
setReturnType(desc); | |||
setReturnType(desc, lineNumber); | |||
return found; | |||
} | |||
@@ -801,10 +801,10 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
} | |||
} | |||
void setReturnType(String desc) throws CompileError { | |||
void setReturnType(String desc, int lineNumber) throws CompileError { | |||
int i = desc.indexOf(')'); | |||
if (i < 0) | |||
badMethod(); | |||
badMethod(lineNumber); | |||
char c = desc.charAt(++i); | |||
int dim = 0; | |||
@@ -817,22 +817,22 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
if (c == 'L') { | |||
int j = desc.indexOf(';', i + 1); | |||
if (j < 0) | |||
badMethod(); | |||
badMethod(lineNumber); | |||
exprType = CLASS; | |||
className = desc.substring(i + 1, j); | |||
} | |||
else { | |||
exprType = MemberResolver.descToType(c); | |||
exprType = MemberResolver.descToType(c, lineNumber); | |||
className = null; | |||
} | |||
} | |||
private void atFieldRead(ASTree expr) throws CompileError { | |||
atFieldRead(fieldAccess(expr)); | |||
atFieldRead(fieldAccess(expr), expr.getLineNumber()); | |||
} | |||
private void atFieldRead(CtField f) throws CompileError { | |||
private void atFieldRead(CtField f, int lineNumber) throws CompileError { | |||
FieldInfo finfo = f.getFieldInfo2(); | |||
String type = finfo.getDescriptor(); | |||
@@ -845,7 +845,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
} | |||
arrayDim = dim; | |||
exprType = MemberResolver.descToType(c); | |||
exprType = MemberResolver.descToType(c, lineNumber); | |||
if (c == 'L') | |||
className = type.substring(i + 1, type.indexOf(';', i + 1)); | |||
@@ -1007,7 +1007,7 @@ public class TypeChecker extends Visitor implements Opcode, TokenId { | |||
protected void atFieldPlusPlus(ASTree oprand) throws CompileError | |||
{ | |||
CtField f = fieldAccess(oprand); | |||
atFieldRead(f); | |||
atFieldRead(f, oprand.getLineNumber()); | |||
int t = exprType; | |||
if (t == INT || t == BYTE || t == CHAR || t == SHORT) | |||
exprType = INT; |
@@ -163,26 +163,26 @@ public class Cast extends Expr { | |||
} | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
if (gen.getMethodArgsLength(args) != 1) | |||
throw new CompileError(Javac.proceedName | |||
+ "() cannot take more than one parameter " | |||
+ "for cast"); | |||
+ "for cast", lineNumber); | |||
gen.atMethodArgs(args, new int[1], new int[1], new String[1]); | |||
bytecode.addOpcode(Opcode.CHECKCAST); | |||
bytecode.addIndex(index); | |||
gen.setType(retType); | |||
gen.setType(retType, lineNumber); | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker c, ASTList args) | |||
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
c.atMethodArgs(args, new int[1], new int[1], new String[1]); | |||
c.setType(retType); | |||
c.setType(retType, lineNumber); | |||
} | |||
} | |||
} |
@@ -259,12 +259,12 @@ public class FieldAccess extends Expr { | |||
} | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
if (args != null && !gen.isParamListName(args)) | |||
throw new CompileError(Javac.proceedName | |||
+ "() cannot take a parameter for field reading"); | |||
+ "() cannot take a parameter for field reading", lineNumber); | |||
int stack; | |||
if (isStatic(opcode)) | |||
@@ -282,14 +282,14 @@ public class FieldAccess extends Expr { | |||
bytecode.add(opcode); | |||
bytecode.addIndex(index); | |||
bytecode.growStack(stack); | |||
gen.setType(fieldType); | |||
gen.setType(fieldType, lineNumber); | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker c, ASTList args) | |||
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
c.setType(fieldType); | |||
c.setType(fieldType, lineNumber); | |||
} | |||
} | |||
@@ -309,13 +309,13 @@ public class FieldAccess extends Expr { | |||
} | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
if (gen.getMethodArgsLength(args) != 1) | |||
throw new CompileError(Javac.proceedName | |||
+ "() cannot take more than one parameter " | |||
+ "for field writing"); | |||
+ "for field writing", lineNumber); | |||
int stack; | |||
if (isStatic(opcode)) | |||
@@ -335,16 +335,16 @@ public class FieldAccess extends Expr { | |||
bytecode.add(opcode); | |||
bytecode.addIndex(index); | |||
bytecode.growStack(stack); | |||
gen.setType(CtClass.voidType); | |||
gen.setType(CtClass.voidType, lineNumber); | |||
gen.addNullIfVoid(); | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker c, ASTList args) | |||
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
c.atMethodArgs(args, new int[1], new int[1], new String[1]); | |||
c.setType(CtClass.voidType); | |||
c.setType(CtClass.voidType, lineNumber); | |||
c.addNullIfVoid(); | |||
} | |||
} |
@@ -167,26 +167,26 @@ public class Instanceof extends Expr { | |||
} | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
if (gen.getMethodArgsLength(args) != 1) | |||
throw new CompileError(Javac.proceedName | |||
+ "() cannot take more than one parameter " | |||
+ "for instanceof"); | |||
+ "for instanceof", lineNumber); | |||
gen.atMethodArgs(args, new int[1], new int[1], new String[1]); | |||
bytecode.addOpcode(Opcode.INSTANCEOF); | |||
bytecode.addIndex(index); | |||
gen.setType(CtClass.booleanType); | |||
gen.setType(CtClass.booleanType, lineNumber); | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker c, ASTList args) | |||
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
c.atMethodArgs(args, new int[1], new int[1], new String[1]); | |||
c.setType(CtClass.booleanType); | |||
c.setType(CtClass.booleanType, lineNumber); | |||
} | |||
} | |||
} |
@@ -270,13 +270,13 @@ public class NewArray extends Expr { | |||
} | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
int num = gen.getMethodArgsLength(args); | |||
if (num != dimension) | |||
throw new CompileError(Javac.proceedName | |||
+ "() with a wrong number of parameters"); | |||
+ "() with a wrong number of parameters", lineNumber); | |||
gen.atMethodArgs(args, new int[num], | |||
new int[num], new String[num]); | |||
@@ -291,14 +291,14 @@ public class NewArray extends Expr { | |||
bytecode.growStack(1 - dimension); | |||
} | |||
gen.setType(arrayType); | |||
gen.setType(arrayType, lineNumber); | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker c, ASTList args) | |||
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
c.setType(arrayType); | |||
c.setType(arrayType, lineNumber); | |||
} | |||
} | |||
} |
@@ -250,7 +250,7 @@ public class NewExpr extends Expr { | |||
} | |||
@Override | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args) | |||
public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
bytecode.addOpcode(NEW); | |||
@@ -258,15 +258,15 @@ public class NewExpr extends Expr { | |||
bytecode.addOpcode(DUP); | |||
gen.atMethodCallCore(newType, MethodInfo.nameInit, args, | |||
false, true, -1, null); | |||
gen.setType(newType); | |||
gen.setType(newType, lineNumber); | |||
} | |||
@Override | |||
public void setReturnType(JvstTypeChecker c, ASTList args) | |||
public void setReturnType(JvstTypeChecker c, ASTList args, int lineNumber) | |||
throws CompileError | |||
{ | |||
c.atMethodCallCore(newType, MethodInfo.nameInit, args); | |||
c.setType(newType); | |||
c.atMethodCallCore(newType, MethodInfo.nameInit, args, lineNumber); | |||
c.setType(newType, lineNumber); | |||
} | |||
} | |||
} |
@@ -13,6 +13,20 @@ public class LineNumberTest extends TestCase { | |||
"}"), "line 3: syntax error near \" return\n}\""); | |||
} | |||
public void testUndevField() { | |||
doTestCompile(String.join("\n", | |||
"public void run() {", | |||
" foo = 5;", | |||
"}"), "line 2: no such field: foo"); | |||
} | |||
public void testUndevMethod() { | |||
doTestCompile(String.join("\n", | |||
"public void run() {", | |||
" foo();", | |||
"}"), "line 2: foo() not found in javassist.LineNumberCompileTest2"); | |||
} | |||
public void testException() { | |||
doTestRuntime(String.join("\n", | |||
"public void run() {", |
@@ -105,11 +105,11 @@ public class CompTest extends TestCase { | |||
public void testArgTypesToString() { | |||
String s; | |||
s = TypeChecker.argTypesToString(new int[0], new int[0], new String[0]); | |||
s = TypeChecker.argTypesToString(new int[0], new int[0], new String[0], 0); | |||
assertEquals("()", s); | |||
s = TypeChecker.argTypesToString(new int[] { TokenId.INT, TokenId.CHAR, TokenId.CLASS }, | |||
new int[] { 0, 1, 0 }, | |||
new String[] { null, null, "String" }); | |||
new String[] { null, null, "String" }, 0); | |||
assertEquals("(int,char[],String)", s); | |||
} | |||