*** empty log message ***

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@47 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 27 years ago
parent 62fb4fc26c
commit 243f1dbed4
  1. 20
      jode/jode/decompiler/LocalInfo.java
  2. 13
      jode/jode/expr/CheckCastOperator.java
  3. 1
      jode/jode/expr/ComplexExpression.java
  4. 13
      jode/jode/expr/InstanceOfOperator.java
  5. 187
      jode/jode/type/ClassRangeType.java

@ -65,14 +65,16 @@ public class LocalInfo {
public void combineWith(LocalInfo li) { public void combineWith(LocalInfo li) {
li = li.getLocalInfo(); li = li.getLocalInfo();
if (shadow != null) { if (shadow != null) {
while (shadow.shadow != null) { getLocalInfo().combineWith(li);
shadow = shadow.shadow; } else {
}
shadow.combineWith(li);
}
if (this != li) { if (this != li) {
shadow = li; shadow = li;
li.setType(type); li.setType(type);
/* Clear unused fields, to allow garbage collection.
*/
type = null;
name = null;
}
} }
} }
@ -127,13 +129,7 @@ public class LocalInfo {
* Get the type of this local. * Get the type of this local.
*/ */
public Type getType() { public Type getType() {
if (shadow != null) { return getLocalInfo().type;
while (shadow.shadow != null) {
shadow = shadow.shadow;
}
return shadow.getType();
}
return type;
} }
/** /**

@ -26,7 +26,18 @@ public class CheckCastOperator extends SimpleOperator {
public CheckCastOperator(Type type, String typeString) { public CheckCastOperator(Type type, String typeString) {
super(type, 0, 1); super(type, 0, 1);
this.typeString = typeString; this.typeString = typeString;
operandTypes[0] = MyType.tSuperType(type); /* The following is wrong. The operand must not
* be a super type of the given type, but any type
* especially if type is an interface.
*
* If operand is of class type, it is probably a
* super type, but who knows?
*
* operandTypes[0] = MyType.tSuperType(type);
*
* The forgiving solution:
*/
operandTypes[0] = MyType.tUnknown;
} }
public int getPriority() { public int getPriority() {

@ -127,6 +127,7 @@ public class ComplexExpression extends Expression {
if (newType != type) { if (newType != type) {
type = newType; type = newType;
operator.setType(type); operator.setType(type);
updateSubTypes();
} }
} }

@ -25,7 +25,18 @@ public class InstanceOfOperator extends SimpleOperator {
public InstanceOfOperator(Type type, String typeString) { public InstanceOfOperator(Type type, String typeString) {
super(Type.tBoolean, 0, 1); super(Type.tBoolean, 0, 1);
this.operandTypes[0] = MyType.tSuperType(type); /* The following is wrong. The operand must not
* be a super type of the given type, but any type
* especially if type is an interface.
*
* If operand is of class type, it is probably a
* super type, but who knows?
*
* this.operandTypes[0] = MyType.tSuperType(type);
*
* The forgiving solution:
*/
this.operandTypes[0] = MyType.tUnknown;
this.typeString = typeString; this.typeString = typeString;
} }
public int getOperandCount() { public int getOperandCount() {

@ -42,6 +42,9 @@ public class ClassRangeType extends MyType {
bottomType = ((ClassRangeType)bottomType).bottomType; bottomType = ((ClassRangeType)bottomType).bottomType;
if (topType != null && topType.getTypeCode() == 103) if (topType != null && topType.getTypeCode() == 103)
topType = ((ClassRangeType)topType).topType; topType = ((ClassRangeType)topType).topType;
typeSig = "-"+
(bottomType == null ? "0" : bottomType.getTypeSignature()) +
(topType == null ? "0" : topType.getTypeSignature());
this.bottomType = bottomType; this.bottomType = bottomType;
this.topType = topType; this.topType = topType;
} }
@ -86,7 +89,9 @@ public class ClassRangeType extends MyType {
top.getTypeCode() <= bottom.getTypeCode()) top.getTypeCode() <= bottom.getTypeCode())
return bottom; return bottom;
if (top.getTypeCode() != 9 && top.getTypeCode() != 10) if (top.getTypeCode() != 9
&& top.getTypeCode() != 10
&& top.getTypeCode() != 104)
return tError; return tError;
if (bottom == null || bottom == tObject) if (bottom == null || bottom == tObject)
@ -101,23 +106,17 @@ public class ClassRangeType extends MyType {
return tArray(type); return tArray(type);
} }
if (bottom.getTypeCode() != 10 || top.getTypeCode() != 10) if (bottom.getTypeCode() == 10)
return tError; bottom = new ClassInterfacesType(bottom);
if (bottom == top)
return bottom;
ClassDeclaration c1 = new ClassDeclaration(bottom.getClassName()); if (top.getTypeCode() == 10)
ClassDeclaration c2 = new ClassDeclaration(top.getClassName()); top = new ClassInterfacesType(top);
try { if (bottom.getTypeCode() != 104 || top.getTypeCode() != 104)
if (c2.getClassDefinition(env).isInterface()
|| c1.getClassDefinition(env).superClassOf(env, c2)
|| c1.getClassDefinition(env).implementedBy(env, c2))
return new ClassRangeType(bottom, top);
} catch (ClassNotFound ex) {
}
return tError; return tError;
return ClassInterfacesType.createRangeType
((ClassInterfacesType) bottom, (ClassInterfacesType) top);
} }
public Type getElementType() { public Type getElementType() {
@ -161,8 +160,12 @@ public class ClassRangeType extends MyType {
return t2; return t2;
} }
if ((t1.getTypeCode() != 9 && t1.getTypeCode() != 10) || if ((t1.getTypeCode() != 9
(t2.getTypeCode() != 9 && t2.getTypeCode() != 10)) && t1.getTypeCode() != 10
&& t1.getTypeCode() != 104)
|| (t2.getTypeCode() != 9
&& t2.getTypeCode() != 10
&& t2.getTypeCode() != 104))
return tError; return tError;
if (t1 == MyType.tObject) if (t1 == MyType.tObject)
@ -174,64 +177,17 @@ public class ClassRangeType extends MyType {
return tArray(getSpecializedType(t1.getElementType(), return tArray(getSpecializedType(t1.getElementType(),
t2.getElementType())); t2.getElementType()));
if (t1.getTypeCode() != 10 || t2.getTypeCode() != 10) if (t1.getTypeCode() == 10)
return tError; t1 = new ClassInterfacesType(t1);
/* Now we have two classes or interfaces. The result should
* be the object that is the the child of both objects resp
* implements both interfaces.
*
* I currently only handle the simple case where one of the
* two objects implements the other or is a child of it.
*
* There are really complicated cases that are currently
* ignored: imaging, c1 and c2 are both disjunct interfaces
* and there are some object which implements them both.
* There is no way for us to guess which.
*
* Another possibility is that c1 is an interface and c2
* an Object that doesn't implement c1. This is not an error,
* because it may be a sub class of c1 and c2 that implements
* c1 and c2.
*
* What can we do about this? We probably need something more
* powerful than a simple class range.
*
* But think of this code fragment:
*
* class Foo implements i1, i2 { ... }
*
* class Bar {
* Foo getFoo() { ... }
* void someFunction() {
* while ((Foo foo = getFoo()) != null) {
* foo.interface1Method();
* foo.interface2Method();
* }
* }
* }
*
* Since the while condition is moved to the bottom of
* the loop, the type information of foo is only available
* <em>after</em> the two interface methods are called.
* The current code would produce tError.
*/
ClassDeclaration c1 = new ClassDeclaration(t1.getClassName()); if (t2.getTypeCode() == 10)
ClassDeclaration c2 = new ClassDeclaration(t2.getClassName()); t2 = new ClassInterfacesType(t2);
try { if (t1.getTypeCode() != 104 || t2.getTypeCode() != 104)
if (c1.getClassDefinition(env).superClassOf(env, c2))
return t2;
if (c2.getClassDefinition(env).superClassOf(env, c1))
return t1;
if (c1.getClassDefinition(env).implementedBy(env, c2))
return t2;
if (c2.getClassDefinition(env).implementedBy(env, c1))
return t1;
} catch (ClassNotFound ex) {
}
return tError; return tError;
return ClassInterfacesType.getSpecializedType
((ClassInterfacesType) t1, (ClassInterfacesType) t2);
} }
/** /**
@ -263,8 +219,12 @@ public class ClassRangeType extends MyType {
else else
return t2; return t2;
} }
if ((t1.getTypeCode() != 9 && t1.getTypeCode() != 10) || if ((t1.getTypeCode() != 9
(t1.getTypeCode() != 9 && t1.getTypeCode() != 10)) && t1.getTypeCode() != 10
&& t1.getTypeCode() != 104)
|| (t2.getTypeCode() != 9
&& t2.getTypeCode() != 10
&& t2.getTypeCode() != 104))
return tError; return tError;
if (t1 == MyType.tObject) if (t1 == MyType.tObject)
@ -272,61 +232,25 @@ public class ClassRangeType extends MyType {
if (t2 == MyType.tObject) if (t2 == MyType.tObject)
return t2; return t2;
if (t1.getTypeCode() == 9 && t2.getTypeCode() == 9) if (t1.getTypeCode() == 9 && t2.getTypeCode() == 9) {
return tArray(getGeneralizedType(t1.getElementType(), Type type = getGeneralizedType(t1.getElementType(),
t2.getElementType())); t2.getElementType());
if (type == null)
return null;
return tArray(type);
}
if (t1.getTypeCode() != 10 || t2.getTypeCode() != 10) if (t1.getTypeCode() == 10)
return tError; t1 = new ClassInterfacesType(t1);
/* This code is not always correct: if (t2.getTypeCode() == 10)
* We don't want a real super type in all cases, but maybe only t2 = new ClassInterfacesType(t2);
* an interface which both objects implement. Think of this:
*
* interface I;
* class C1 implements I;
* class C2 implements I;
*
* {
* I var;
* if (cond)
* var = getC1();
* else
* var = getC2();
* return var.interfaceMethod();
* }
*
* The current code would first assign the type object to
* var and then produce a type error when interfaceMethod
* is called.
*
* Now we have proved that we need some better concept for
* types. (Maybe a set of types for the upper and lower
* bound)
*/
ClassDeclaration c1 = new ClassDeclaration(t1.getClassName());
ClassDeclaration c2 = new ClassDeclaration(t2.getClassName());
try { if (t1.getTypeCode() != 104 || t2.getTypeCode() != 104)
/* if one of the two types is an interface, return return tError;
* the other type, since at least a subtype of the
* other type may implement the interface.
*/
if (c1.getClassDefinition(env).isInterface())
return t2;
if (c2.getClassDefinition(env).isInterface())
return t1;
ClassDefinition c = c1.getClassDefinition(env); return ClassInterfacesType.getGeneralizedType
while(c != null && !c.superClassOf(env, c2)) { ((ClassInterfacesType) t1, (ClassInterfacesType) t2);
c = c.getSuperClass(env).getClassDefinition(env);
}
if (c != null)
return tClass(c.getName());
} catch (ClassNotFound ex) {
}
return tObject;
} }
public Type getIntersection(ClassRangeType type) public Type getIntersection(ClassRangeType type)
@ -360,14 +284,15 @@ public class ClassRangeType extends MyType {
{ {
if (Decompiler.isTypeDebugging) if (Decompiler.isTypeDebugging)
return "<"+bottomType+"-"+topType+">" + string; return "<"+bottomType+"-"+topType+">" + string;
else if (topType != null)
return topType.typeString(string, flag1, flag2);
else if (bottomType != null) else if (bottomType != null)
/* This means, that the local variable is never assigned to.
* If bottom type is a ClassRangeType, there may be problems,
* that are ignored. They produce compiler errors.
*/
return bottomType.typeString(string, flag1, flag2); return bottomType.typeString(string, flag1, flag2);
else else
return tObject.typeString(string, flag1, flag2); return "<Unknown>"+string;
} }
// public String toString()
// {
// return "<"+bottomType+"-"+topType+">";
// }
} }

Loading…
Cancel
Save