class ClassResolutionFailedException extends ResolutionFailedException {
    /** */
    private static final long serialVersionUID = 5430199603403917938L;

    public ClassResolutionFailedException() {
      super("Class " + declaringClass + " doesn't have method " + name + "(" + (parameterTypes == null ? "" : parameterTypes)
          + ")" + " : " + returnType + "; failed to resolve in superclasses and interfaces");
    }

    @Override
    public String toString() {
      final StringBuilder ret = new StringBuilder(super.toString());
      resolve(ret);
      return ret.toString();
    }
  }

  @Override
  public SootMethod resolve() {
    SootMethod cached = this.resolveCache;
    // Use the cached SootMethod if available and still valid
    if (cached == null || !cached.isValidResolve(this)) {
      cached = resolve(null);
      this.resolveCache = cached;
    }
    return cached;
  }

  @Override
  public SootMethod tryResolve() {
    return tryResolve(null);
  }

  private void checkStatic(SootMethod method) {
    final int opt = Options.v().wrong_staticness();
    if ((opt == Options.wrong_staticness_fail || opt == Options.wrong_staticness_fixstrict)
        && method.isStatic() != isStatic() && !method.isPhantom()) {
      throw new ResolutionFailedException("Resolved " + this + " to " + method + " which has wrong static-ness");
    }
  }

  protected SootMethod tryResolve(final StringBuilder trace) {
    // let's do a dispatch and allow abstract method for resolution
    // we do not have a base object for call so we just take the type of the declaring class
    SootMethod resolved = Scene.v().getOrMakeFastHierarchy().resolveMethod(declaringClass, declaringClass, name,
        parameterTypes, returnType, true, this.getSubSignature());

    if (resolved != null) {
      checkStatic(resolved);
      return resolved;
    } else if (Scene.v().allowsPhantomRefs()) {
      // Try to resolve in the current class and the interface,
      // if not found check for phantom class in the superclass.
      for (SootClass selectedClass = declaringClass; selectedClass != null;) {
        if (selectedClass.isPhantom()) {
          SootMethod phantomMethod
              = Scene.v().makeSootMethod(name, parameterTypes, returnType, isStatic() ? Modifier.STATIC : 0);
          phantomMethod.setPhantom(true);
          phantomMethod = selectedClass.getOrAddMethod(phantomMethod);
          checkStatic(phantomMethod);
          return phantomMethod;
        }
        selectedClass = selectedClass.getSuperclassUnsafe();
      }
    }

    // If we don't have a method yet, we try to fix it on the fly
    if (Scene.v().allowsPhantomRefs() && Options.v().ignore_resolution_errors()) {
      // if we have a phantom class in the hierarchy, we add the method to it.
      SootClass classToAddTo = declaringClass;
      while (classToAddTo != null && !classToAddTo.isPhantom()) {
        classToAddTo = classToAddTo.getSuperclassUnsafe();
      }

      // We just take the declared class, otherwise.
      if (classToAddTo == null) {
        classToAddTo = declaringClass;
      }

      SootMethod method = Scene.v().makeSootMethod(name, parameterTypes, returnType, isStatic() ? Modifier.STATIC : 0);
      method.setPhantom(true);
      method = classToAddTo.getOrAddMethod(method);
      checkStatic(method);
      return method;
    }

    return null;
  }

  private SootMethod resolve(final StringBuilder trace) {
    SootMethod resolved = tryResolve(trace);
    if (resolved != null) {
      return resolved;
    }

    // When allowing phantom refs we also allow for references to non-existing
    // methods. We simply create the methods on the fly. The method body will
    // throw an appropriate error just in case the code *is* actually reached
    // at runtime. Furthermore, the declaring class of dynamic invocations is
    // not known at compile time, treat as phantom class regardless if phantom
    // classes are enabled or not.
    if (Options.v().allow_phantom_refs() || SootClass.INVOKEDYNAMIC_DUMMY_CLASS_NAME.equals(declaringClass.getName())) {
      return createUnresolvedErrorMethod(declaringClass);
    }

    if (trace == null) {
      ClassResolutionFailedException e = new ClassResolutionFailedException();
      if (Options.v().ignore_resolution_errors()) {
        logger.debug(e.getMessage());
      } else {
        throw e;
      }
    }

    return null;
  }

  /**
   * Creates a method body that throws an "unresolved compilation error" message
   *
   * @param declaringClass
   *          The class that was supposed to contain the method
   * @return The created SootMethod
   */
  private SootMethod createUnresolvedErrorMethod(SootClass declaringClass) {<FILL_FUNCTION_BODY>

    final Jimple jimp = Jimple.v();

    SootMethod m = Scene.v().makeSootMethod(name, parameterTypes, returnType, isStatic() ? Modifier.STATIC : 0);
    int modifiers = Modifier.PUBLIC; // we don't know who will be calling us
    if (isStatic()) {
      modifiers |= Modifier.STATIC;
    }
    m.setModifiers(modifiers);
    JimpleBody body = jimp.newBody(m);
    m.setActiveBody(body);

    final LocalGenerator lg = Scene.v().createLocalGenerator(body);

    // For producing valid Jimple code, we need to access all parameters.
    // Otherwise, methods like "getThisLocal()" will fail.
    body.insertIdentityStmts(declaringClass);

    // exc = new Error
    RefType runtimeExceptionType = RefType.v("java.lang.Error");
    if (Options.v().src_prec() == Options.src_prec_dotnet) {
      runtimeExceptionType = RefType.v(DotnetBasicTypes.SYSTEM_EXCEPTION);
    }
    Local exceptionLocal = lg.generateLocal(runtimeExceptionType);
    AssignStmt assignStmt = jimp.newAssignStmt(exceptionLocal, jimp.newNewExpr(runtimeExceptionType));
    body.getUnits().add(assignStmt);

    // exc.<init>(message)
    SootMethodRef cref = Scene.v().makeConstructorRef(runtimeExceptionType.getSootClass(),
        Collections.<Type>singletonList(RefType.v("java.lang.String")));
    if (Options.v().src_prec() == Options.src_prec_dotnet) {
      cref = Scene.v().makeConstructorRef(runtimeExceptionType.getSootClass(),
          Collections.<Type>singletonList(RefType.v(DotnetBasicTypes.SYSTEM_STRING)));
    }
    SpecialInvokeExpr constructorInvokeExpr = jimp.newSpecialInvokeExpr(exceptionLocal, cref,
        StringConstant.v("Unresolved compilation error: Method " + getSignature() + " does not exist!"));
    InvokeStmt initStmt = jimp.newInvokeStmt(constructorInvokeExpr);
    body.getUnits().insertAfter(initStmt, assignStmt);

    // throw exc
    body.getUnits().insertAfter(jimp.newThrowStmt(exceptionLocal), initStmt);

    return declaringClass.getOrAddMethod(m);
  
<no_super_class>