Additional check in ParameterAccessor
getThisAs tests for supertype now
This commit is contained in:
parent
5f51dac201
commit
cc2ffec023
|
@ -287,11 +287,13 @@ public class ParameterAccessor { // extends Param-Manager
|
||||||
*
|
*
|
||||||
* Do _not_ use ParameterAceesor(IMethod.getReference()), but ParameterAceesor(IMehod)!
|
* Do _not_ use ParameterAceesor(IMethod.getReference()), but ParameterAceesor(IMehod)!
|
||||||
*
|
*
|
||||||
* Using this Constructor influences the SSA-Values returned later.
|
* Using this Constructor influences the SSA-Values returned later. The cha is needed to
|
||||||
|
* determine whether mRef is static. If this is already known one should prefer the faster
|
||||||
|
* {@link #ParameterAccessor(ParameterAccessor, boolean)}.
|
||||||
*
|
*
|
||||||
* @param mRef The method to read the parameters from.
|
* @param mRef The method to read the parameters from.
|
||||||
*/
|
*/
|
||||||
public ParameterAccessor(final MethodReference mRef, final IClassHierarchy cha) { // TODO :document
|
public ParameterAccessor(final MethodReference mRef, final IClassHierarchy cha) {
|
||||||
if (mRef == null) {
|
if (mRef == null) {
|
||||||
throw new IllegalArgumentException("Can't read the arguments from null.");
|
throw new IllegalArgumentException("Can't read the arguments from null.");
|
||||||
}
|
}
|
||||||
|
@ -373,7 +375,7 @@ public class ParameterAccessor { // extends Param-Manager
|
||||||
if (hasImplicitThis) {
|
if (hasImplicitThis) {
|
||||||
logger.info("The method {} has an implicit this pointer", mRef);
|
logger.info("The method {} has an implicit this pointer", mRef);
|
||||||
this.implicitThis = 1;
|
this.implicitThis = 1;
|
||||||
this.descriptorOffset = -1; // TODO: verify
|
this.descriptorOffset = -1;
|
||||||
} else {
|
} else {
|
||||||
logger.info("The method {} has no implicit this pointer", mRef);
|
logger.info("The method {} has no implicit this pointer", mRef);
|
||||||
this.implicitThis = -1;
|
this.implicitThis = -1;
|
||||||
|
@ -381,8 +383,16 @@ public class ParameterAccessor { // extends Param-Manager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
public ParameterAccessor(final MethodReference mRef, final boolean hasImplicitThis) { // TODO :document
|
* Reads the parameters of a MethodReference CAUTION:.
|
||||||
|
*
|
||||||
|
* Do _not_ use ParameterAceesor(IMethod.getReference()), but ParameterAceesor(IMehod)!
|
||||||
|
*
|
||||||
|
* This constructor is faster than {@link #ParameterAccessor(MethodReference, IClassHierarchy}.
|
||||||
|
*
|
||||||
|
* @param mRef The method to read the parameters from.
|
||||||
|
*/
|
||||||
|
public ParameterAccessor(final MethodReference mRef, final boolean hasImplicitThis) {
|
||||||
if (mRef == null) {
|
if (mRef == null) {
|
||||||
throw new IllegalArgumentException("Can't read the arguments from null.");
|
throw new IllegalArgumentException("Can't read the arguments from null.");
|
||||||
}
|
}
|
||||||
|
@ -395,7 +405,7 @@ public class ParameterAccessor { // extends Param-Manager
|
||||||
if (hasImplicitThis) {
|
if (hasImplicitThis) {
|
||||||
logger.info("The method {} has an implicit this pointer", mRef);
|
logger.info("The method {} has an implicit this pointer", mRef);
|
||||||
this.implicitThis = 1;
|
this.implicitThis = 1;
|
||||||
this.descriptorOffset = -1; // TODO: verify
|
this.descriptorOffset = -1;
|
||||||
} else {
|
} else {
|
||||||
logger.info("The method {} has no implicit this pointer", mRef);
|
logger.info("The method {} has no implicit this pointer", mRef);
|
||||||
this.implicitThis = -1;
|
this.implicitThis = -1;
|
||||||
|
@ -449,8 +459,6 @@ public class ParameterAccessor { // extends Param-Manager
|
||||||
// no is checked by getParameterNo(int)
|
// no is checked by getParameterNo(int)
|
||||||
final int newNo = getParameterNo(no);
|
final int newNo = getParameterNo(no);
|
||||||
|
|
||||||
//assert(false):"DEFECT!";
|
|
||||||
|
|
||||||
switch (this.base) {
|
switch (this.base) {
|
||||||
case IMETHOD: // TODO: Try reading parameter name
|
case IMETHOD: // TODO: Try reading parameter name
|
||||||
return new Parameter(newNo, null, this.method.getParameterType(no), ParamerterDisposition.PARAM,
|
return new Parameter(newNo, null, this.method.getParameterType(no), ParamerterDisposition.PARAM,
|
||||||
|
@ -582,22 +590,35 @@ public class ParameterAccessor { // extends Param-Manager
|
||||||
return getThisAs(selfType);
|
return getThisAs(selfType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the implicit this-pointer as a supertype.
|
||||||
|
*
|
||||||
|
* @param asType A type of a super-class of this
|
||||||
|
*/
|
||||||
public Parameter getThisAs(final TypeReference asType) {
|
public Parameter getThisAs(final TypeReference asType) {
|
||||||
// TODO assert asType is a subtype of self.type
|
|
||||||
final int self = getThisNo();
|
final int self = getThisNo();
|
||||||
|
|
||||||
switch (this.base) {
|
switch (this.base) {
|
||||||
case IMETHOD:
|
case IMETHOD:
|
||||||
|
final IClassHierarchy cha = this.method.getClassHierarchy();
|
||||||
|
try {
|
||||||
|
if (! isSubclassOf(this.method.getParameterType(self), asType, cha) ) {
|
||||||
|
throw new IllegalArgumentException("Class " + asType + " is not a super-class of " +
|
||||||
|
this.method.getParameterType(self));
|
||||||
|
}
|
||||||
|
} catch (ClassLookupException e) {
|
||||||
|
// Cant't test assume all fitts
|
||||||
|
}
|
||||||
|
|
||||||
return new Parameter(self, "self", asType, ParamerterDisposition.THIS,
|
return new Parameter(self, "self", asType, ParamerterDisposition.THIS,
|
||||||
this.base, this.method.getReference(), this.descriptorOffset);
|
this.base, this.method.getReference(), this.descriptorOffset);
|
||||||
case METHOD_REFERENCE:
|
case METHOD_REFERENCE:
|
||||||
|
// TODO assert asType is a subtype of self.type - we need cha to do that :(
|
||||||
return new Parameter(self, "self", asType, ParamerterDisposition.THIS,
|
return new Parameter(self, "self", asType, ParamerterDisposition.THIS,
|
||||||
this.base, this.mRef, this.descriptorOffset);
|
this.base, this.mRef, this.descriptorOffset);
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("No implementation of getThis() for base " + this.base);
|
throw new UnsupportedOperationException("No implementation of getThis() for base " + this.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1257,7 +1278,6 @@ public class ParameterAccessor { // extends Param-Manager
|
||||||
if (callee.getNumberOfParameters() == 0) {
|
if (callee.getNumberOfParameters() == 0) {
|
||||||
return new ArrayList<SSAValue>(0);
|
return new ArrayList<SSAValue>(0);
|
||||||
}
|
}
|
||||||
//final Logger logger = LoggerFactory.getLogger(ParameterAccessor.class); // XXX
|
|
||||||
|
|
||||||
final List<SSAValue> assigned = new ArrayList<SSAValue>(); // TODO: Set initial size
|
final List<SSAValue> assigned = new ArrayList<SSAValue>(); // TODO: Set initial size
|
||||||
final List<Parameter> calleeParams = callee.all();
|
final List<Parameter> calleeParams = callee.all();
|
||||||
|
@ -1480,6 +1500,62 @@ public class ParameterAccessor { // extends Param-Manager
|
||||||
return cha.isAssignableFrom(toClass, fromClass);
|
return cha.isAssignableFrom(toClass, fromClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is sub a subclass of superC (or the same).
|
||||||
|
*/
|
||||||
|
public static boolean isSubclassOf(final TypeReference sub, final TypeReference superC, final IClassHierarchy cha)
|
||||||
|
throws ClassLookupException {
|
||||||
|
if (cha == null) {
|
||||||
|
throw new IllegalArgumentException("ClassHierarchy may not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sub.getName().equals(superC.getName())) return true;
|
||||||
|
|
||||||
|
if (sub.isPrimitiveType() || superC.isPrimitiveType()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IClass subClass = cha.lookupClass(sub);
|
||||||
|
IClass superClass = cha.lookupClass(superC);
|
||||||
|
|
||||||
|
if (subClass == null) {
|
||||||
|
logger.debug("Unable to look up the type of from=" + sub + " in the ClassHierarchy - tying other loaders...");
|
||||||
|
for (final IClassLoader loader: cha.getLoaders()) {
|
||||||
|
final IClass cand = loader.lookupClass(sub.getName());
|
||||||
|
if (cand != null) {
|
||||||
|
logger.debug("Using alternative for from: {}", cand);
|
||||||
|
subClass = cand;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subClass == null) {
|
||||||
|
throw new ClassLookupException("Unable to look up the type of from=" + sub +
|
||||||
|
" in the ClassHierarchy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superClass == null) {
|
||||||
|
logger.debug("Unable to look up the type of to=" + superC + " in the ClassHierarchy - tying other loaders...");
|
||||||
|
for (final IClassLoader loader: cha.getLoaders()) {
|
||||||
|
final IClass cand = loader.lookupClass(superC.getName());
|
||||||
|
if (cand != null) {
|
||||||
|
logger.debug("Using alternative for to: {}", cand);
|
||||||
|
superClass = cand;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superClass == null) {
|
||||||
|
logger.error("Unable to look up the type of to={} in the ClassHierarchy", superC);
|
||||||
|
throw new ClassLookupException("Unable to look up the type of to=" + superC +
|
||||||
|
" in the ClassHierarchy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cha.isSubclassOf(subClass, superClass);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method this accessor reads the parameters from.
|
* The method this accessor reads the parameters from.
|
||||||
*/
|
*/
|
||||||
|
@ -1528,7 +1604,17 @@ public class ParameterAccessor { // extends Param-Manager
|
||||||
return (getReturnType() != TypeReference.Void);
|
return (getReturnType() != TypeReference.Void);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign parameters to a call based on their type.
|
||||||
|
*
|
||||||
|
* this variant of connectThrough cannot create new instances if needed.
|
||||||
|
*
|
||||||
|
* @param callee The function to generate the parameter-list for
|
||||||
|
* @param overrides If a parameter occurs here, it is preferred over the ones present in this
|
||||||
|
* @param defaults If a parameter is not present in this or the overrides, defaults are searched. If the parameter is not present there null is assigned.
|
||||||
|
* @param cha Optional class hierarchy for testing assignability
|
||||||
|
* @return the parameter-list for the call of toMethod
|
||||||
|
*/
|
||||||
public List<SSAValue> connectThrough(final ParameterAccessor callee, Set<? extends SSAValue> overrides, Set<? extends SSAValue> defaults,
|
public List<SSAValue> connectThrough(final ParameterAccessor callee, Set<? extends SSAValue> overrides, Set<? extends SSAValue> defaults,
|
||||||
final IClassHierarchy cha) {
|
final IClassHierarchy cha) {
|
||||||
return connectThrough(callee, overrides, defaults, cha, null);
|
return connectThrough(callee, overrides, defaults, cha, null);
|
||||||
|
@ -1551,10 +1637,16 @@ public class ParameterAccessor { // extends Param-Manager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of parameters _excluding_ implicit this
|
||||||
|
*/
|
||||||
public int getNumberOfParameters() {
|
public int getNumberOfParameters() {
|
||||||
return this.numberOfParameters;
|
return this.numberOfParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extensive output for debugging purposes.
|
||||||
|
*/
|
||||||
public String dump() {
|
public String dump() {
|
||||||
String ret = "Parameter Accessor for " + ((this.mRef!=null)?"mRef:" + this.mRef.toString():"IMethod: " + this.method.toString()) +
|
String ret = "Parameter Accessor for " + ((this.mRef!=null)?"mRef:" + this.mRef.toString():"IMethod: " + this.method.toString()) +
|
||||||
"\nContains " + this.numberOfParameters + " Parameters " + this.base + "\n";
|
"\nContains " + this.numberOfParameters + " Parameters " + this.base + "\n";
|
||||||
|
|
Loading…
Reference in New Issue