*** empty log message ***

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@47 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 62fb4fc26c
commit 243f1dbed4
  1. 24
      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. 201
      jode/jode/type/ClassRangeType.java

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

@ -26,7 +26,18 @@ public class CheckCastOperator extends SimpleOperator {
public CheckCastOperator(Type type, String typeString) {
super(type, 0, 1);
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() {

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

@ -25,7 +25,18 @@ public class InstanceOfOperator extends SimpleOperator {
public InstanceOfOperator(Type type, String typeString) {
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;
}
public int getOperandCount() {

@ -42,6 +42,9 @@ public class ClassRangeType extends MyType {
bottomType = ((ClassRangeType)bottomType).bottomType;
if (topType != null && topType.getTypeCode() == 103)
topType = ((ClassRangeType)topType).topType;
typeSig = "-"+
(bottomType == null ? "0" : bottomType.getTypeSignature()) +
(topType == null ? "0" : topType.getTypeSignature());
this.bottomType = bottomType;
this.topType = topType;
}
@ -86,7 +89,9 @@ public class ClassRangeType extends MyType {
top.getTypeCode() <= bottom.getTypeCode())
return bottom;
if (top.getTypeCode() != 9 && top.getTypeCode() != 10)
if (top.getTypeCode() != 9
&& top.getTypeCode() != 10
&& top.getTypeCode() != 104)
return tError;
if (bottom == null || bottom == tObject)
@ -101,23 +106,17 @@ public class ClassRangeType extends MyType {
return tArray(type);
}
if (bottom.getTypeCode() != 10 || top.getTypeCode() != 10)
if (bottom.getTypeCode() == 10)
bottom = new ClassInterfacesType(bottom);
if (top.getTypeCode() == 10)
top = new ClassInterfacesType(top);
if (bottom.getTypeCode() != 104 || top.getTypeCode() != 104)
return tError;
if (bottom == top)
return bottom;
ClassDeclaration c1 = new ClassDeclaration(bottom.getClassName());
ClassDeclaration c2 = new ClassDeclaration(top.getClassName());
try {
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 ClassInterfacesType.createRangeType
((ClassInterfacesType) bottom, (ClassInterfacesType) top);
}
public Type getElementType() {
@ -161,10 +160,14 @@ public class ClassRangeType extends MyType {
return t2;
}
if ((t1.getTypeCode() != 9 && t1.getTypeCode() != 10) ||
(t2.getTypeCode() != 9 && t2.getTypeCode() != 10))
if ((t1.getTypeCode() != 9
&& t1.getTypeCode() != 10
&& t1.getTypeCode() != 104)
|| (t2.getTypeCode() != 9
&& t2.getTypeCode() != 10
&& t2.getTypeCode() != 104))
return tError;
if (t1 == MyType.tObject)
return t2;
if (t2 == MyType.tObject)
@ -174,64 +177,17 @@ public class ClassRangeType extends MyType {
return tArray(getSpecializedType(t1.getElementType(),
t2.getElementType()));
if (t1.getTypeCode() != 10 || t2.getTypeCode() != 10)
if (t1.getTypeCode() == 10)
t1 = new ClassInterfacesType(t1);
if (t2.getTypeCode() == 10)
t2 = new ClassInterfacesType(t2);
if (t1.getTypeCode() != 104 || t2.getTypeCode() != 104)
return tError;
/* 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());
ClassDeclaration c2 = new ClassDeclaration(t2.getClassName());
try {
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 ClassInterfacesType.getSpecializedType
((ClassInterfacesType) t1, (ClassInterfacesType) t2);
}
/**
@ -263,70 +219,38 @@ public class ClassRangeType extends MyType {
else
return t2;
}
if ((t1.getTypeCode() != 9 && t1.getTypeCode() != 10) ||
(t1.getTypeCode() != 9 && t1.getTypeCode() != 10))
if ((t1.getTypeCode() != 9
&& t1.getTypeCode() != 10
&& t1.getTypeCode() != 104)
|| (t2.getTypeCode() != 9
&& t2.getTypeCode() != 10
&& t2.getTypeCode() != 104))
return tError;
if (t1 == MyType.tObject)
return t1;
if (t2 == MyType.tObject)
return t2;
if (t1.getTypeCode() == 9 && t2.getTypeCode() == 9)
return tArray(getGeneralizedType(t1.getElementType(),
t2.getElementType()));
if (t1.getTypeCode() == 9 && t2.getTypeCode() == 9) {
Type type = getGeneralizedType(t1.getElementType(),
t2.getElementType());
if (type == null)
return null;
return tArray(type);
}
if (t1.getTypeCode() != 10 || t2.getTypeCode() != 10)
return tError;
if (t1.getTypeCode() == 10)
t1 = new ClassInterfacesType(t1);
/* This code is not always correct:
* We don't want a real super type in all cases, but maybe only
* 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 one of the two types is an interface, return
* 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;
if (t2.getTypeCode() == 10)
t2 = new ClassInterfacesType(t2);
ClassDefinition c = c1.getClassDefinition(env);
while(c != null && !c.superClassOf(env, c2)) {
c = c.getSuperClass(env).getClassDefinition(env);
}
if (c != null)
return tClass(c.getName());
} catch (ClassNotFound ex) {
}
return tObject;
if (t1.getTypeCode() != 104 || t2.getTypeCode() != 104)
return tError;
return ClassInterfacesType.getGeneralizedType
((ClassInterfacesType) t1, (ClassInterfacesType) t2);
}
public Type getIntersection(ClassRangeType type)
@ -360,14 +284,15 @@ public class ClassRangeType extends MyType {
{
if (Decompiler.isTypeDebugging)
return "<"+bottomType+"-"+topType+">" + string;
else if (bottomType != null)
return bottomType.typeString(string, flag1, flag2);
else if (topType != null)
return topType.typeString(string, flag1, flag2);
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);
else
return tObject.typeString(string, flag1, flag2);
return "<Unknown>"+string;
}
// public String toString()
// {
// return "<"+bottomType+"-"+topType+">";
// }
}

Loading…
Cancel
Save