overrides the visitor to look for an exact call to the parent class's method using this methods parm.

@param seen
the currently parsed instruction
509463
@Override
    public void sawOpcode(int seen) {

        if (!sawAload0) {
            if (seen == Const.ALOAD_0) {
                sawAload0 = true;
            } else {
                throw new StopOpcodeParsingException();
            }
        } else if (nextParmIndex < parmTypes.length) {
            if (isExpectedParmInstruction(seen, nextParmOffset, parmTypes[nextParmIndex])) {
                nextParmOffset += SignatureUtils.getSignatureSize(parmTypes[nextParmIndex].getSignature());
                nextParmIndex++;
            } else {
                throw new StopOpcodeParsingException();
            }

        } else if (!sawParentCall) {

            if ((seen == Const.INVOKESPECIAL) && getNameConstantOperand().equals(getMethod().getName())
                    && getSigConstantOperand().equals(getMethod().getSignature())) {
                sawParentCall = true;
            } else {
                throw new StopOpcodeParsingException();
            }
        } else {
            int expectedInstruction = getExpectedReturnInstruction(getMethod().getReturnType());
            if ((seen == expectedInstruction) && (getNextPC() == getCode().getCode().length)) {
                bugReporter.reportBug(
                        new BugInstance(this, BugType.COM_PARENT_DELEGATED_CALL.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
            } else {
                throw new StopOpcodeParsingException();
            }
        }
    }
418410
@Override
    public void sawOpcode(int seen) {
        if (seen != Const.INVOKESPECIAL) {
            sawOpenInAppendMode = false;
            return;
        }
        String calledClassName = getClassConstantOperand();
        String calledMethodName = getNameConstantOperand();
        String calledMethodSig = getSigConstantOperand();
        if (!sawOpenInAppendMode) {
            if ("java/io/ObjectOutputStream".equals(calledClassName) && Const.CONSTRUCTOR_NAME.equals(calledMethodName)
                    && "(Ljava/io/OutputStream;)V".equals(calledMethodSig)
                    && stack.getStackItem(0).getSpecialKind() == OpcodeStack.Item.FILE_OPENED_IN_APPEND_MODE) {
                bugReporter.reportBug(new BugInstance(this, "IO_APPENDING_TO_OBJECT_OUTPUT_STREAM", Priorities.HIGH_PRIORITY)
                .addClassAndMethod(this).addSourceLine(this));
            }
            return;
        }
        if ("java/io/FileOutputStream".equals(calledClassName) && Const.CONSTRUCTOR_NAME.equals(calledMethodName)
                && ("(Ljava/io/File;Z)V".equals(calledMethodSig) || "(Ljava/lang/String;Z)V".equals(calledMethodSig))) {
            OpcodeStack.Item item = stack.getStackItem(0);
            Object value = item.getConstant();
            sawOpenInAppendMode = value instanceof Integer && ((Integer) value).intValue() == 1;
        } else if ("java/io/BufferedOutputStream".equals(calledClassName) && Const.CONSTRUCTOR_NAME.equals(calledMethodName)
                && "(Ljava/io/OutputStream;)V".equals(calledMethodSig)) {
            // do nothing

        } else if ("java/io/ObjectOutputStream".equals(calledClassName) && Const.CONSTRUCTOR_NAME.equals(calledMethodName)
                && "(Ljava/io/OutputStream;)V".equals(calledMethodSig)) {
            bugReporter.reportBug(new BugInstance(this, "IO_APPENDING_TO_OBJECT_OUTPUT_STREAM", Priorities.HIGH_PRIORITY)
                .addClassAndMethod(this).addSourceLine(this));
            sawOpenInAppendMode = false;
        } else {
            sawOpenInAppendMode = false;
        }

    }
869163
@Override
    public void sawOpcode(int seen) {
        switch (state) {
            case COLLECT:
                if ((seen == Const.INVOKESTATIC) || (seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKEINTERFACE) || (seen == Const.INVOKESPECIAL)) {
                    refClasses.add(getClassConstantOperand());
                    String signature = getSigConstantOperand();
                    Type[] argTypes = Type.getArgumentTypes(signature);
                    for (Type t : argTypes) {
                        addType(t);
                    }
                    Type resultType = Type.getReturnType(signature);
                    addType(resultType);
                }
            break;

            case SEEN_NOTHING:
                if ((seen == Const.LDC) || (seen == Const.LDC_W)) {
                    Constant c = getConstantRefOperand();
                    if (c instanceof ConstantString) {
                        clsName = ((ConstantString) c).getBytes(getConstantPool());
                        state = State.SEEN_LDC;
                    }
                }
            break;

            case SEEN_LDC:
                if ((seen == Const.INVOKESTATIC) && "forName".equals(getNameConstantOperand()) && "java/lang/Class".equals(getClassConstantOperand())
                        && refClasses.contains(clsName)) {
                    bugReporter.reportBug(new BugInstance(this, BugType.SCR_SLOPPY_CLASS_REFLECTION.name(), NORMAL_PRIORITY).addClass(this).addMethod(this)
                            .addSourceLine(this));
                }
                state = State.SEEN_NOTHING;
            break;
        }
    }
735711
@Override
    public void sawOpcode(int seen) {
        if (seen == Const.INVOKEVIRTUAL) {
            if ("equals".equals(getNameConstantOperand()) && "(Ljava/lang/Object;)Z".equals(getSigConstantOperand())) {
                OpcodeStack.Item item = stack.getStackItem(1);
                ClassDescriptor c = DescriptorFactory.createClassDescriptorFromSignature(item.getSignature());
                check(c);

            } else if ("java/lang/Class".equals(getClassConstantOperand())
                    && ("isInstance".equals(getNameConstantOperand()) || "cast".equals(getNameConstantOperand()))) {
                OpcodeStack.Item item = stack.getStackItem(1);
                if ("Ljava/lang/Class;".equals(item.getSignature())) {
                    Object value = item.getConstant();
                    if (value instanceof String) {
                        ClassDescriptor c = DescriptorFactory.createClassDescriptor((String) value);
                        check(c);
                    }
                }

            }

        } else if (seen == Const.INSTANCEOF || seen == Const.CHECKCAST) {
            check(getClassDescriptorOperand());
        }

    }
194587
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(value = "CLI_CONSTANT_LIST_INDEX", justification = "Constrained by FindBugs API")
    @Override
    public void sawOpcode(int seen) {

        PSCUserValue userValue = null;
        boolean sawAlloc = false;

        try {
            stack.precomputation(this);

            switch (seen) {
                case Const.INVOKESPECIAL:
                    String clsName = getClassConstantOperand();
                    if (PRESIZEABLE_COLLECTIONS.contains(clsName)) {
                        String methodName = getNameConstantOperand();
                        if (Values.CONSTRUCTOR.equals(methodName)) {
                            String signature = getSigConstantOperand();
                            if (SignatureBuilder.SIG_VOID_TO_VOID.equals(signature)) {
                                userValue = new PSCUserValue(Integer.valueOf(nextAllocNumber++));
                                sawAlloc = true;
                            } else if (guavaOnPath && (stack.getStackDepth() > 0)) {
                                FQMethod fqMethod = new FQMethod(clsName, methodName, signature);
                                if (HASHMAP_SIZED_CTOR.equals(fqMethod) || HASHSET_SIZED_CTOR.equals(fqMethod)) {
                                    OpcodeStack.Item itm = stack.getStackItem(0);
                                    XMethod xm = itm.getReturnValueOf();
                                    if ((xm != null) && "size".equals(xm.getMethodDescriptor().getName())) {
                                        bugReporter.reportBug(new BugInstance(this, BugType.PSC_SUBOPTIMAL_COLLECTION_SIZING.name(), NORMAL_PRIORITY)
                                                .addClass(this).addMethod(this).addSourceLine(this));
                                    }
                                }
                            }
                        }
                    }
                break;

                case Const.INVOKEINTERFACE:
                    String methodName = getNameConstantOperand();

                    if (ITERATOR_METHOD.equals(new QMethod(methodName, getSigConstantOperand()))) {
                        if (stack.getStackDepth() > 0) {
                            OpcodeStack.Item itm = stack.getStackItem(0);
                            userValue = isSizedSource(itm);
                        }
                    } else if (ITERATOR_HASNEXT.equals(new FQMethod(getClassConstantOperand(), methodName, getSigConstantOperand()))) {
                        if (stack.getStackDepth() > 0) {
                            OpcodeStack.Item itm = stack.getStackItem(0);
                            userValue = (PSCUserValue) itm.getUserValue();
                        }
                    } else if ("add".equals(methodName) || "addAll".equals(methodName)) {
                        String signature = getSigConstantOperand();
                        int numArguments = SignatureUtils.getNumParameters(signature);
                        if ((numArguments == 1) && (stack.getStackDepth() > 1)) {
                            OpcodeStack.Item item = stack.getStackItem(1);
                            PSCUserValue uv = (PSCUserValue) item.getUserValue();
                            if (uv != null) {
                                Integer allocNum = uv.getAllocationNumber();
                                if (allocNum != null) {
                                    if ("addAll".equals(methodName)) {
                                        allocToAddPCs.remove(allocNum);
                                    } else {
                                        List<Integer> lines = allocToAddPCs.get(allocNum);
                                        if (lines == null) {
                                            lines = new ArrayList<>();
                                            allocToAddPCs.put(allocNum, lines);
                                        }
                                        lines.add(Integer.valueOf(getPC()));
                                    }
                                }
                            }
                        }
                    } else if ("put".equals(methodName) || "putAll".equals(methodName)) {
                        String signature = getSigConstantOperand();
                        int numArguments = SignatureUtils.getNumParameters(signature);
                        if ((numArguments == 2) && (stack.getStackDepth() > 2)) {
                            OpcodeStack.Item item = stack.getStackItem(2);
                            PSCUserValue uv = (PSCUserValue) item.getUserValue();
                            if (uv != null) {
                                Integer allocNum = uv.getAllocationNumber();
                                if (allocNum != null) {
                                    if ("putAll".equals(methodName)) {
                                        allocToAddPCs.remove(allocNum);
                                    } else {
                                        List<Integer> lines = allocToAddPCs.get(allocNum);
                                        if (lines == null) {
                                            lines = new ArrayList<>();
                                            allocToAddPCs.put(allocNum, lines);
                                        }
                                        lines.add(Integer.valueOf(getPC()));
                                    }
                                }
                            }
                        }
                    }
                break;

                case Const.INVOKESTATIC:
                    FQMethod fqm = new FQMethod(getClassConstantOperand(), getNameConstantOperand(), getSigConstantOperand());
                    if (STATIC_COLLECTION_FACTORIES.contains(fqm)) {
                        userValue = new PSCUserValue(Integer.valueOf(nextAllocNumber++));
                        sawAlloc = true;
                    }
                break;

                case Const.LOOKUPSWITCH:
                case Const.TABLESWITCH:
                    int[] offsets = getSwitchOffsets();
                    if (offsets.length >= 2) {
                        int pc = getPC();
                        int thisOffset = pc + offsets[0];
                        for (int o = 0; o < (offsets.length - 1); o++) {
                            int nextOffset = offsets[o + 1] + pc;
                            CodeRange db = new CodeRange(thisOffset, nextOffset, false);
                            optionalRanges.add(db);
                            thisOffset = nextOffset;
                        }
                    }
                break;

                case Const.IFEQ:
                case Const.IFNE:
                case Const.IFLT:
                case Const.IFLE:
                case Const.IF_ICMPEQ:
                case Const.IF_ICMPNE:
                case Const.IF_ICMPLT:
                case Const.IF_ICMPGE:
                case Const.IF_ICMPGT:
                case Const.IF_ICMPLE:
                case Const.IF_ACMPEQ:
                case Const.IF_ACMPNE:
                case Const.GOTO:
                case Const.GOTO_W:
                    if (getBranchOffset() < 0) {

                        if (branchBasedOnUnsizedObject(seen)) {
                            break;
                        }

                        int target = getBranchTarget();
                        Iterator<Map.Entry<Integer, List<Integer>>> it = allocToAddPCs.entrySet().iterator();
                        while (it.hasNext()) {
                            Map.Entry<Integer, List<Integer>> entry = it.next();
                            Integer allocLoc = allocLocation.get(entry.getKey());
                            if ((allocLoc != null) && (allocLoc.intValue() < target)) {
                                List<Integer> pcs = entry.getValue();
                                for (int pc : pcs) {
                                    if (pc > target) {
                                        if (hasSinglePossiblySizedBranch(allocLoc.intValue(), pc)) {
                                            bugReporter.reportBug(new BugInstance(this, BugType.PSC_PRESIZE_COLLECTIONS.name(), NORMAL_PRIORITY).addClass(this)
                                                    .addMethod(this).addSourceLine(this, pc));
                                            it.remove();
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    } else {
                        CodeRange db = new CodeRange(getPC(), getBranchTarget(), !branchBasedOnUnsizedObject(seen));
                        optionalRanges.add(db);
                    }
                break;

                case Const.IFNULL:
                case Const.IFNONNULL:
                case Const.IFGE:
                case Const.IFGT:
                    // null check and >, >= branches are hard to presize
                    if (getBranchOffset() > 0) {
                        CodeRange db = new CodeRange(getPC(), getBranchTarget(), false);
                        optionalRanges.add(db);
                    }
                break;

                case Const.ASTORE:
                case Const.ASTORE_0:
                case Const.ASTORE_1:
                case Const.ASTORE_2:
                case Const.ASTORE_3: {
                    if (stack.getStackDepth() > 0) {
                        PSCUserValue uv = (PSCUserValue) stack.getStackItem(0).getUserValue();
                        if (uv != null) {
                            storeToUserValue.put(getRegisterOperand(), uv);
                        }
                    }
                }
                break;

                case Const.ALOAD:
                case Const.ALOAD_0:
                case Const.ALOAD_1:
                case Const.ALOAD_2:
                case Const.ALOAD_3: {
                    userValue = storeToUserValue.get(getRegisterOperand());
                }
                break;

                case Const.PUTFIELD: {
                    if (stack.getStackDepth() > 0) {
                        PSCUserValue uv = (PSCUserValue) stack.getStackItem(0).getUserValue();
                        if (uv != null) {
                            storeToUserValue.put(getNameConstantOperand(), uv);
                        }
                    }
                }
                break;

                case Const.GETFIELD: {
                    userValue = storeToUserValue.get(getNameConstantOperand());
                }
                break;

            }
        } finally {
            stack.sawOpcode(this, seen);
            if ((userValue != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(userValue);
                if (sawAlloc) {
                    allocLocation.put(userValue.getAllocationNumber(), Integer.valueOf(getPC()));
                }
            }
        }
    }
1241418
@Override
    public void sawOpcode(int seen) {
        CCIUserValue userValue = null;
        try {
            stack.precomputation(this);

            switch (seen) {
                case Const.INVOKESPECIAL:
                    if ("java/util/concurrent/ConcurrentHashMap".equals(getClassConstantOperand()) && Values.CONSTRUCTOR.equals(getNameConstantOperand())) {
                        userValue = CCIUserValue.CONCURRENT_HASHMAP;
                    }
                break;

                case Const.INVOKEINTERFACE:
                case Const.INVOKEVIRTUAL:
                    if ("get".equals(getNameConstantOperand())) {
                        if (stack.getStackDepth() >= 2) {
                            OpcodeStack.Item itm = stack.getStackItem(1);
                            if (itm.getUserValue() == CCIUserValue.CONCURRENT_HASHMAP) {
                                userValue = CCIUserValue.CONCURRENT_HASHMAP_VALUE;
                            }
                        }
                    } else if ("put".equals(getNameConstantOperand()) && (endNullCheckPC > getPC()) && (stack.getStackDepth() >= 3)) {
                        OpcodeStack.Item mapItem = stack.getStackItem(2);

                        if (mapItem.getUserValue() == CCIUserValue.CONCURRENT_HASHMAP) {
                            OpcodeStack.Item valueItem = stack.getStackItem(0);
                            JavaClass valueClass = valueItem.getJavaClass();
                            if ((valueClass != null) && (valueClass.instanceOf(collectionClass) || valueClass.instanceOf(mapClass))) {

                                bugReporter.reportBug(new BugInstance(this, BugType.CCI_CONCURRENT_COLLECTION_ISSUES_USE_PUT_IS_RACY.name(), NORMAL_PRIORITY)
                                        .addClass(this).addMethod(this).addSourceLine(this));
                            }
                        }
                    }
                break;

                case Const.PUTFIELD:
                case Const.PUTSTATIC:
                    if (stack.getStackDepth() >= 1) {
                        OpcodeStack.Item itm = stack.getStackItem(0);
                        CCIUserValue uv = (CCIUserValue) itm.getUserValue();
                        if (uv != null) {
                            fieldUserValues.put(getNameConstantOperand(), uv);
                        } else {
                            fieldUserValues.remove(getNameConstantOperand());
                        }
                    }
                break;

                case Const.GETFIELD:
                case Const.GETSTATIC:
                    userValue = fieldUserValues.get(getNameConstantOperand());
                break;

                case Const.IFNONNULL:
                    if ((getBranchOffset() > 0) && (stack.getStackDepth() > 0)) {
                        OpcodeStack.Item itm = stack.getStackItem(0);
                        if (itm.getUserValue() == CCIUserValue.CONCURRENT_HASHMAP_VALUE) {
                            endNullCheckPC = getBranchTarget();
                        }
                    }
                break;
            }

        } catch (ClassNotFoundException e) {
            bugReporter.reportMissingClass(e);
        } finally {
            stack.sawOpcode(this, seen);
            if ((userValue != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item itm = stack.getStackItem(0);
                itm.setUserValue(userValue);
            }

            if (getPC() >= endNullCheckPC) {
                endNullCheckPC = -1;
            }
        }
    }
1263647
private void sawOpcodeLoop(final int seen) {
        try {
            stack.mergeJumps(this);

            switch (state) {
                case SAW_NOTHING:
                    if ((seen == Const.IINC) && (getIntConstant() == 1)) {
                        loopReg = getRegisterOperand();
                        state = State.SAW_IINC;
                    }
                break;

                case SAW_IINC:
                    if ((seen == Const.GOTO) || (seen == Const.GOTO_W)) {
                        int branchTarget = getBranchTarget();
                        int pc = getPC();
                        if (branchTarget < pc) {
                            possibleForLoops.add(new ForLoop(branchTarget, pc, loopReg));
                        }
                    }
                    state = State.SAW_NOTHING;
                break;
            }

            if ((seen == Const.INVOKEINTERFACE) && Values.SLASHED_JAVA_UTIL_LIST.equals(getClassConstantOperand()) && "size".equals(getNameConstantOperand())
                    && SignatureBuilder.SIG_VOID_TO_INT.equals(getSigConstantOperand())) {
                sawListSize = true;
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
494019
@Override
    public void sawOpcode(final int seen) {
        if (OpcodeUtils.isAStore(seen)) {
            changedParms.set(RegisterUtils.getAStoreReg(this, seen));
        }
    }
863100
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            int pc = getPC();
            CodeException ex = catchHandlerPCs.get(Integer.valueOf(pc));
            if (ex != null) {
                int endPC;
                if ((seen == Const.GOTO) || (seen == Const.GOTO_W)) {
                    endPC = this.getBranchTarget();
                } else {
                    endPC = Integer.MAX_VALUE;
                }
                ConstantPool pool = getConstantPool();
                ConstantClass ccls = (ConstantClass) pool.getConstant(ex.getCatchType());
                String catchSig = ccls.getBytes(pool);
                CatchInfo ci = new CatchInfo(ex.getHandlerPC(), endPC, catchSig);
                catchInfos.add(ci);
            }

            updateEndPCsOnCatchRegScope(catchInfos, pc, seen);
            removeFinishedCatchBlocks(catchInfos, pc);

            if (seen == Const.ATHROW) {
                processThrow();
            } else if ((seen == Const.IRETURN) && isBooleanMethod && !hasValidFalseReturn && (stack.getStackDepth() > 0)) {
                processBooleanReturn();
            }

        } finally {
            stack.sawOpcode(this, seen);
        }
    }
1071352
@Override
    public void sawOpcode(int seen) {
        String methodInfo = null;
        try {
            stack.precomputation(this);

            switch (seen) {
                case Const.INVOKEVIRTUAL:
                case Const.INVOKEINTERFACE:
                case Const.INVOKESTATIC:
                    String sig = getSigConstantOperand();
                    if (!sig.endsWith(Values.SIG_VOID)) {
                        methodInfo = getClassConstantOperand() + '@' + getNameConstantOperand() + getSigConstantOperand();
                    }
                break;

                case Const.POP:
                case Const.POP2:
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        String mInfo = (String) item.getUserValue();
                        if (mInfo != null) {
                            for (Pattern p : IMMUTABLE_METHODS) {
                                Matcher m = p.matcher(mInfo);

                                if (m.matches()) {
                                    bugReporter.reportBug(new BugInstance(this, BugType.NPMC_NON_PRODUCTIVE_METHOD_CALL.name(), NORMAL_PRIORITY).addClass(this)
                                            .addMethod(this).addSourceLine(this).addString(mInfo));
                                    break;
                                }
                            }
                        }
                    }
                break;
            }

        } finally {
            stack.sawOpcode(this, seen);
            if ((methodInfo != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(methodInfo);
            }
        }
    }
1217657
@Override
    public void sawOpcode(int seen) {
        switch (state) {
            case IN_CLINIT:
                sawCLInitOpcode(seen);
            break;

            case IN_INIT:
                sawInitOpcode(seen);
            break;

            case IN_METHOD:
                sawMethodOpcode(seen);
            break;
        }
    }
1011865
@Override
    public void sawOpcode(final int seen) {
        Object hashCodedStringRef = null;
        try {
            stack.precomputation(this);

            switch (seen) {
                case Const.INVOKEVIRTUAL:
                    if (Values.SLASHED_JAVA_LANG_STRING.equals(getClassConstantOperand())) {
                        String calledMethodName = getNameConstantOperand();
                        String calledMethodSig = getSigConstantOperand();

                        if (("equals".equals(calledMethodName) && SignatureBuilder.SIG_OBJECT_TO_BOOLEAN.equals(calledMethodSig))
                                || ("compareTo".equals(calledMethodName) && SignatureBuilder.SIG_STRING_TO_INT.equals(calledMethodSig))
                                || ("equalsIgnoreCase".equals(calledMethodName) && SignatureBuilder.SIG_STRING_TO_BOOLEAN.equals(calledMethodSig))) {

                            if (stack.getStackDepth() > 0) {
                                OpcodeStack.Item itm = stack.getStackItem(0);
                                Object constant = itm.getConstant();
                                if ((constant != null) && constant.getClass().equals(String.class) && !lookupSwitchOnString()) {
                                    bugReporter.reportBug(new BugInstance(this, "LSC_LITERAL_STRING_COMPARISON", HIGH_PRIORITY) // very
                                                                                                                                // confident
                                            .addClass(this).addMethod(this).addSourceLine(this));
                                }
                            }
                        } else if (Values.HASHCODE.equals(calledMethodName) && (stack.getStackDepth() > 0)) {
                            OpcodeStack.Item item = stack.getStackItem(0);
                            int reg = item.getRegisterNumber();
                            if (reg >= 0) {
                                hashCodedStringRef = String.valueOf(reg);
                            } else {
                                XField xf = item.getXField();
                                if (xf != null) {
                                    hashCodedStringRef = xf.getName();
                                } else {
                                    XMethod xm = item.getReturnValueOf();
                                    if (xm != null) {
                                        hashCodedStringRef = xm.toString();
                                    }
                                }

                            }
                        }
                    }
                break;

                case Const.TABLESWITCH:
                case Const.LOOKUPSWITCH:
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        String stringRef = (String) item.getUserValue();
                        if (stringRef != null) {
                            int[] offsets = getSwitchOffsets();
                            BitSet bs = new BitSet();
                            int pc = getPC();
                            for (int offset : offsets) {
                                bs.set(pc + offset);
                            }
                            bs.set(pc + getDefaultSwitchOffset());
                            lookupSwitches.add(new LookupDetails(stringRef, bs));
                        }
                    }
                break;
                default:
                break;
            }

        } finally {
            stack.sawOpcode(this, seen);
            if ((hashCodedStringRef != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(hashCodedStringRef);
            }

            if (!lookupSwitches.isEmpty()) {
                int innerMostSwitch = lookupSwitches.size() - 1;
                LookupDetails details = lookupSwitches.get(innerMostSwitch);
                if (details.getSwitchTargets().get(getPC()) && (stack.getStackDepth() > 0)) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    item.setUserValue(details.getStringReference());
                }

                // previousSetBit is a jdk1.7 api - gonna cheat cause findbugs
                // runs on 1.7
                if (getPC() >= details.getSwitchTargets().previousSetBit(Integer.MAX_VALUE)) {
                    lookupSwitches.remove(innerMostSwitch);
                }
            }
        }
    }
480743
@Override
	public void sawOpcode(int seen) {
        if ((seen == Const.INVOKEVIRTUAL) && "printStackTrace".equals(getNameConstantOperand())
				&& SignatureBuilder.SIG_VOID_TO_VOID.equals(getSigConstantOperand())) {
			bugReporter
					.reportBug(new BugInstance(this, BugType.IMC_IMMATURE_CLASS_PRINTSTACKTRACE.name(), NORMAL_PRIORITY)
							.addClass(this).addMethod(this).addSourceLine(this));
		}
	}
750084
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            int pc = getPC();
            if ((loopEnd != -1) && (pc > loopEnd)) {
                loopStart = -1;
                loopEnd = -1;
                regValueType.clear();
            }

            if (OpcodeUtils.isALoad(seen)) {
                int reg = RegisterUtils.getALoadReg(this, seen);
                State type = regValueType.get(Integer.valueOf(reg));
                if (type == null) {
                    state = State.SEEN_NOTHING;
                } else {
                    state = type;
                }
                return;
            }
            if (OpcodeUtils.isAStore(seen)) {
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    int reg = RegisterUtils.getAStoreReg(this, seen);
                    regValueType.put(Integer.valueOf(reg), (State) item.getUserValue());
                }
                state = State.SEEN_NOTHING;
                return;
            }
            if (OpcodeUtils.isILoad(seen)) {
                int reg = RegisterUtils.getLoadReg(this, seen);
                State type = regValueType.get(Integer.valueOf(reg));
                if (type == null) {
                    state = State.SEEN_NOTHING;
                } else {
                    state = type;
                }
                return;
            }
            if (OpcodeUtils.isIStore(seen)) {
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item item = stack.getStackItem(0);
                    int reg = RegisterUtils.getStoreReg(this, seen);
                    regValueType.put(Integer.valueOf(reg), (State) item.getUserValue());
                }
                state = State.SEEN_NOTHING;
                return;
            }

            switch (state) {
                case SEEN_NOTHING:
                    if ((seen == Const.INVOKESPECIAL) && "java/util/StringTokenizer".equals(getClassConstantOperand())
                            && Values.CONSTRUCTOR.equals(getNameConstantOperand())
                            && SignatureBuilder.SIG_TWO_STRINGS_TO_VOID.equals(getSigConstantOperand())) {
                        state = State.SEEN_STRINGTOKENIZER;
                    }
                break;

                case SEEN_STRINGTOKENIZER:
                    if (seen == Const.INVOKEVIRTUAL) {
                        String methodName = getNameConstantOperand();
                        String signature = getSigConstantOperand();
                        if ("countTokens".equals(methodName) && SignatureBuilder.SIG_VOID_TO_INT.equals(signature))
                            state = State.SEEN_COUNTTOKENS;
                        else if ("hasMoreTokens".equals(methodName) || "hasMoreElements".equals(methodName))
                            state = State.SEEN_HASMORE;
                        else if ("nextToken".equals(methodName) || "nextElement".equals(methodName)) {
                            if ((pc < loopStart) || (pc > loopEnd))
                                regValueType.clear();
                            else
                                state = State.SEEN_NEXT;
                        }
                    }
                break;

                case SEEN_COUNTTOKENS:
                    if (seen == Const.ANEWARRAY)
                        state = State.SEEN_NEWARRAY;
                    else if (seen == Const.IF_ICMPGE) {
                        int target = getBranchTarget() - 3;// sizeof goto
                        byte[] code = getCode().getCode();
                        if ((code[target] & 0x000000FF) == Const.GOTO) {
                            int offset = (code[target + 1] << 1) + code[target + 2];
                            int gotoTarget = target + offset + 3;
                            if (gotoTarget < getPC()) {
                                loopStart = gotoTarget;
                                loopEnd = target;
                            }
                        }
                    }
                break;

                case SEEN_HASMORE:
                    if (seen == Const.IFEQ) {
                        int target = getBranchTarget() - 3;// sizeof goto
                        byte[] code = getCode().getCode();
                        if ((code[target] & 0x000000FF) == Const.GOTO) {
                            int offset = (code[target + 1] << 1) + code[target + 2];
                            int gotoTarget = target + offset + 3;
                            if (gotoTarget < getPC()) {
                                loopStart = gotoTarget;
                                loopEnd = target;
                            }
                        }
                    }
                    state = State.SEEN_NOTHING;
                break;

                case SEEN_NEXT:
                    if ((seen == Const.AASTORE) && (pc > loopStart) && (pc < loopEnd) && (stack.getStackDepth() > 2)) {
                        OpcodeStack.Item arrayItem = stack.getStackItem(2);
                        State arrayType = (State) arrayItem.getUserValue();
                        OpcodeStack.Item elemItem = stack.getStackItem(0);
                        State elemType = (State) elemItem.getUserValue();
                        if ((arrayType == State.SEEN_NEWARRAY) && (elemType == State.SEEN_NEXT)) {
                            bugReporter.reportBug(new BugInstance(this, BugType.USS_USE_STRING_SPLIT.name(), NORMAL_PRIORITY).addClass(this).addMethod(this)
                                    .addSourceLine(this));
                        }
                    }
                    state = State.SEEN_NOTHING;
                break;

                case SEEN_ARRAYSTORE:
                case SEEN_NEWARRAY:
                break;
            }
        } finally {
            TernaryPatcher.pre(stack, seen);
            stack.sawOpcode(this, seen);
            TernaryPatcher.post(stack, seen);
            if ((state != State.SEEN_NOTHING) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(state);
            }
        }
    }
206541
private void sawInitOpcode(int seen) {
        boolean isSyncCollection = false;
        try {
            stack.mergeJumps(this);
            isSyncCollection = isSyncCollectionCreation(seen);
            if (seen == Const.PUTFIELD) {
                processCollectionStore();
            }
        } finally {
            stack.sawOpcode(this, seen);
            if (isSyncCollection && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(Boolean.TRUE);
            }
        }
    }
311899
@Override
    public void sawOpcode(int seen) {
        try {
            switch (state) {
                case SAW_NOTHING:
                    sawOpcodeAfterNothing(seen);
                break;

                case SAW_EQUALS:
                    sawOpcodeAfterEquals(seen);
                break;

                case SAW_IFEQ:
                    sawOpcodeAfterBranch(seen);
                break;
            }

            processLoad(seen);
            processLoop(seen);
        } finally {
            stack.sawOpcode(this, seen);
        }

    }
877615
@Override
    public void sawOpcode(int seen) {

        String message = null;
        try {
            stack.precomputation(this);

            if ((seen == Const.TABLESWITCH) || (seen == Const.LOOKUPSWITCH)) {
                int pc = getPC();
                for (int offset : getSwitchOffsets()) {
                    transitionPoints.set(pc + offset);
                }
                transitionPoints.set(pc + getDefaultSwitchOffset());
            } else if (isBranch(seen) && (getBranchOffset() < 0)) {
                // throw out try blocks in loops, this could cause false
                // negatives
                // with two try/catches in one loop, but more unlikely
                Iterator<TryBlock> it = blocks.iterator();
                int target = getBranchTarget();
                while (it.hasNext()) {
                    TryBlock block = it.next();
                    if (block.getStartPC() >= target) {
                        it.remove();
                    }
                }
            }

            int pc = getPC();
            TryBlock block = findBlockWithStart(pc);
            if (block != null) {
                inBlocks.add(block);
                block.setState(TryBlock.State.IN_TRY);
            }

            if (inBlocks.isEmpty()) {
                return;
            }
            TryBlock innerBlock = inBlocks.get(inBlocks.size() - 1);

            int nextPC = getNextPC();
            if (innerBlock.atHandlerPC(nextPC)) {
                if ((seen == Const.GOTO) || (seen == Const.GOTO_W)) {
                    innerBlock.setEndHandlerPC(getBranchTarget());
                } else {
                    inBlocks.remove(innerBlock);
                    blocks.remove(innerBlock);
                }
            } else if (innerBlock.atHandlerPC(pc)) {
                innerBlock.setState(TryBlock.State.IN_CATCH);
            } else if (innerBlock.atEndHandlerPC(pc)) {
                inBlocks.remove(inBlocks.size() - 1);
                innerBlock.setState(TryBlock.State.AFTER);
            }

            if (transitionPoints.get(nextPC)) {
                if (innerBlock.inCatch() && (innerBlock.getEndHandlerPC() > nextPC)) {
                    innerBlock.setEndHandlerPC(nextPC);
                }
            }

            if (innerBlock.inCatch()) {
                if (((seen >= Const.IFEQ) && ((seen <= Const.RET))) || (seen == Const.GOTO_W) || OpcodeUtils.isReturn(seen)) {
                    blocks.remove(innerBlock);
                    inBlocks.remove(inBlocks.size() - 1);
                } else if (seen == Const.ATHROW) {
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        XMethod xm = item.getReturnValueOf();
                        if (xm != null) {
                            innerBlock.setThrowSignature(xm.getSignature());
                        }
                        innerBlock.setExceptionSignature(item.getSignature());
                        innerBlock.setMessage((String) item.getUserValue());
                    } else {
                        inBlocks.remove(inBlocks.size() - 1);
                        innerBlock.setState(TryBlock.State.AFTER);
                    }
                } else if ((seen == Const.INVOKESPECIAL) && Values.CONSTRUCTOR.equals(getNameConstantOperand())) {
                    String cls = getClassConstantOperand();
                    JavaClass exCls = Repository.lookupClass(cls);
                    if (exCls.instanceOf(THROWABLE_CLASS)) {
                        String signature = getSigConstantOperand();
                        List<String> types = SignatureUtils.getParameterSignatures(signature);
                        if (!types.isEmpty()) {
                            if (Values.SIG_JAVA_LANG_STRING.equals(types.get(0)) && (stack.getStackDepth() >= types.size())) {
                                OpcodeStack.Item item = stack.getStackItem(types.size() - 1);
                                message = (String) item.getConstant();
                                if (message == null) {
                                    message = "____UNKNOWN____" + System.identityHashCode(item);
                                }
                            }
                        } else {
                            message = "";
                        }
                    }
                }
            }
        } catch (ClassNotFoundException cnfe) {
            bugReporter.reportMissingClass(cnfe);
        } finally {
            stack.sawOpcode(this, seen);
            if ((message != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(message);
            }
        }
    }