/**
   * Clone non-static ancestor methods that are not hidden by virtual dispatch and that are
   * reachable based on a pta run.
   */
  private void cloneReachableNonHiddenAncestorMethods(SootClass ancestor) {
    if (ClassCloner.isClonedClass(ancestor)) {
      logger.error("Cloning method from clone: {}", ancestor);
      droidsafe.main.Main.exit(1);
    }

    // create all methods, cloning body, replacing instance field refs
    for (SootMethod ancestorM : ancestor.getMethods()) {
      if (ancestorM.isAbstract()
          || ancestorM.isPhantom()
          || !ancestorM.isConcrete()
          || SootUtils.isRuntimeStubMethod(ancestorM)) continue;

      // never clone static methods
      if (ancestorM.isStatic()) continue;

      // clone only reachable methods
      if (!cloneAllMethods && !PTABridge.v().getReachableMethods().contains(ancestorM)) continue;

      // check if this method already exists
      if (containsMethod(ancestorM.getSignature())) {
        // System.out.printf("\tAlready contains method %s.\n", ancestorM);
        continue;
      }

      // turn off final for ancestor methods
      if (ancestorM.isFinal()) ancestorM.setModifiers(ancestorM.getModifiers() ^ Modifier.FINAL);

      cloneMethod(ancestorM, ancestorM.getName());
    }
  }