public void visitINVOKEINTERFACE()

in src/main/java/org/apache/bcel/verifier/structurals/InstConstraintVisitor.java [1557:1637]


    public void visitINVOKEINTERFACE(final INVOKEINTERFACE o) {
        // Method is not native, otherwise pass 3 would not happen.

        final int count = o.getCount();
        if (count == 0) {
            constraintViolated(o, "The 'count' argument must not be 0.");
        }
        // It is a ConstantInterfaceMethodref, Pass 3a made it sure.
        // TODO: Do we want to do anything with it?
        // ConstantInterfaceMethodref cimr = (ConstantInterfaceMethodref) (cpg.getConstant(o.getIndex()));

        // the o.getClassType(cpg) type has passed pass 2; see visitLoadClass(o).

        final Type t = o.getType(cpg);
        if (t instanceof ObjectType) {
            final String name = ((ObjectType) t).getClassName();
            final Verifier v = VerifierFactory.getVerifier(name);
            final VerificationResult vr = v.doPass2();
            if (vr.getStatus() != VerificationResult.VERIFIED_OK) {
                constraintViolated(o, "Class '" + name + "' is referenced, but cannot be loaded and resolved: '" + vr + "'.");
            }
        }

        final Type[] argTypes = o.getArgumentTypes(cpg);
        final int argCount = argTypes.length;

        for (int i = argCount - 1; i >= 0; i--) {
            final Type fromStack = stack().peek(argCount - 1 - i); // 0 to argCount - 1
            Type fromDesc = argTypes[i];
            if (fromDesc == Type.BOOLEAN || fromDesc == Type.BYTE || fromDesc == Type.CHAR || fromDesc == Type.SHORT) {
                fromDesc = Type.INT;
            }
            if (!fromStack.equals(fromDesc)) {
                if (fromStack instanceof ReferenceType && fromDesc instanceof ReferenceType) {
                    final ReferenceType rFromStack = (ReferenceType) fromStack;
                    // ReferenceType rFromDesc = (ReferenceType) fromDesc;
                    // TODO: This can only be checked when using Staerk-et-al's "set of object types"
                    // instead of a "wider cast object type" created during verification.
                    // if ( ! rFromStack.isAssignmentCompatibleWith(rFromDesc) ) {
                    // constraintViolated(o, "Expecting a '"+fromDesc+"' but found a '"+fromStack+
                    // "' on the stack (which is not assignment compatible).");
                    // }
                    referenceTypeIsInitialized(o, rFromStack);
                } else {
                    constraintViolated(o, "Expecting a '" + fromDesc + "' but found a '" + fromStack + "' on the stack.");
                }
            }
        }

        Type objRef = stack().peek(argCount);
        if (objRef == Type.NULL) {
            return;
        }
        if (!(objRef instanceof ReferenceType)) {
            constraintViolated(o, "Expecting a reference type as 'objectref' on the stack, not a '" + objRef + "'.");
        }
        referenceTypeIsInitialized(o, (ReferenceType) objRef);
        if (!(objRef instanceof ObjectType)) {
            if (!(objRef instanceof ArrayType)) { // could be a ReturnaddressType
                constraintViolated(o, "Expecting an ObjectType as 'objectref' on the stack, not a '" + objRef + "'.");
            } else {
                objRef = GENERIC_ARRAY;
            }
        }

        // String objRefClassName = ((ObjectType) objRef).getClassName();
        // String theInterface = o.getClassName(cpg);
        // TODO: This can only be checked if we're using Staerk-et-al's "set of object types"
        // instead of "wider cast object types" generated during verification.
        // if ( ! Repository.implementationOf(objRefClassName, theInterface) ) {
        // constraintViolated(o, "The 'objRef' item '" + objRef + "' does not implement '" + theInterface + "' as expected.");
        // }

        int countedCount = 1; // 1 for the objectref
        for (int i = 0; i < argCount; i++) {
            countedCount += argTypes[i].getSize();
        }
        if (count != countedCount) {
            constraintViolated(o, "The 'count' argument should probably read '" + countedCount + "' but is '" + count + "'.");
        }
    }