public Set<SootMethod> resolveAbstractDispatch(SootClass abstractType,SootMethod m){
  String methodSig=m.getSubSignature();
  HashSet<SootClass> resolved=new HashSet<SootClass>();
  HashSet<SootMethod> ret=new HashSet<SootMethod>();
  LinkedList<SootClass> worklist=new LinkedList<SootClass>();
  worklist.add(abstractType);
  while (!worklist.isEmpty()) {
    SootClass concreteType=(SootClass)worklist.removeFirst();
    SootClass savedConcreteType=concreteType;
    if (concreteType.isInterface()) {
      worklist.addAll(getAllImplementersOfInterface(concreteType));
      continue;
    }
    Collection<SootClass> c=classToSubclasses.get(concreteType);
    if (c != null)     worklist.addAll(c);
    if (!concreteType.isAbstract()) {
      while (true) {
        if (resolved.contains(concreteType))         break;
        resolved.add(concreteType);
        SootMethod method=concreteType.getMethodUnsafe(methodSig);
        if (method != null) {
          if (isVisible(concreteType,m)) {
            if (method.isAbstract())             throw new RuntimeException("abstract dispatch resolved to abstract method!\nAbstract Type: " + abstractType + "\nConcrete Type: "+ savedConcreteType+ "\nMethod: "+ m);
 else {
              ret.add(method);
              break;
            }
          }
        }
        if (!concreteType.hasSuperclass()) {
          if (concreteType.isPhantom())           break;
 else           throw new RuntimeException("could not resolve abstract dispatch!\nAbstract Type: " + abstractType + "\nConcrete Type: "+ savedConcreteType+ "\nMethod: "+ m);
        }
        concreteType=concreteType.getSuperclass();
      }
    }
  }
  return ret;
}

public Set < SootMethod > resolveAbstractDispatch ( SootClass abstractType , SootMethod m ) { String methodSig = m . getSubSignature ( ) ; HashSet < SootClass > resolved = new HashSet < SootClass > ( ) ; HashSet < SootMethod > ret = new HashSet < SootMethod > ( ) ; LinkedList < SootClass > worklist = new LinkedList < SootClass > ( ) ; worklist . add ( abstractType ) ; while ( ! worklist . isEmpty ( ) ) { SootClass concreteType = ( SootClass ) worklist . removeFirst ( ) ; SootClass savedConcreteType = concreteType ; if ( concreteType . isInterface ( ) ) { worklist . addAll ( getAllImplementersOfInterface ( concreteType ) ) ; continue ; } Collection < SootClass > c = classToSubclasses . get ( concreteType ) ; if ( c != null ) worklist . addAll ( c ) ; if ( ! concreteType . isAbstract ( ) ) { while ( true ) { if ( resolved . contains ( concreteType ) ) break ; resolved . add ( concreteType ) ; SootMethod method = concreteType . getMethodUnsafe ( methodSig ) ; if ( method != null ) { if ( isVisible ( concreteType , m ) ) { if ( method . isAbstract ( ) ) throw new RuntimeException ( "abstract dispatch resolved to abstract method!\nAbstract Type: " + abstractType + "\nConcrete Type: " + savedConcreteType + "\nMethod: " + m ) ; else { ret . add ( method ) ; break ; } } } if ( ! concreteType . hasSuperclass ( ) ) { if ( concreteType . isPhantom ( ) ) break ; else throw new RuntimeException ( "could not resolve abstract dispatch!\nAbstract Type: " + abstractType + "\nConcrete Type: " + savedConcreteType + "\nMethod: " + m ) ; } concreteType = concreteType . getSuperclass ( ) ; } } } return ret ; }
given an object of declared type c , returns the methods which could be called on an o . f ( ) invocation .
