implements the visitor to look for calls to Logger.getLogger with the wrong class name

@param seen
the opcode of the currently parsed instruction
505589
@Override
    @SuppressWarnings("unchecked")
    public void sawOpcode(int seen) {
        String ldcClassName = null;
        String seenMethodName = null;
        boolean seenToString = false;
        boolean seenFormatterLogger = false;
        int exMessageReg = -1;
        Integer arraySize = null;
        boolean simpleFormat = false;

        try {
            stack.precomputation(this);

            if ((seen == Const.LDC) || (seen == Const.LDC_W)) {
                Constant c = getConstantRefOperand();
                if (c instanceof ConstantClass) {
                    ConstantPool pool = getConstantPool();
                    ldcClassName = ((ConstantUtf8) pool.getConstant(((ConstantClass) c).getNameIndex())).getBytes();
                }
            } else if (seen == Const.INVOKESTATIC) {
                lookForSuspectClasses();

                String clsName = getClassConstantOperand();
                String methodName = getNameConstantOperand();
                if (Values.SLASHED_JAVA_LANG_STRING.equals(clsName) && "format".equals(methodName) && (stack.getStackDepth() >= 2)) {
                    String format = (String) stack.getStackItem(1).getConstant();
                    if (format != null) {
                        Matcher m = NON_SIMPLE_FORMAT.matcher(format);
                        if (!m.matches()) {
                            simpleFormat = true;
                        }
                    }
                } else if ("getFormatterLogger".equals(methodName) && LOG4J2_LOGMANAGER.equals(clsName)) {
                    seenFormatterLogger = true;
                }
            } else if (((seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKEINTERFACE)) && (throwableClass != null)) {
                String mthName = getNameConstantOperand();
                if ("getName".equals(mthName)) {
                    if (stack.getStackDepth() >= 1) {
                        // Foo.class.getName() is being called, so we pass the
                        // name of the class to the current top of the stack
                        // (the name of the class is currently on the top of the
                        // stack, but won't be on the stack at all next opcode)
                        Item stackItem = stack.getStackItem(0);
                        LOUserValue<String> uv = (LOUserValue<String>) stackItem.getUserValue();
                        if ((uv != null) && (uv.getType() == LOUserValue.LOType.CLASS_NAME)) {
                            ldcClassName = uv.getValue();
                        }
                    }
                } else if ("getMessage".equals(mthName)) {
                    String callingClsName = getClassConstantOperand();
                    JavaClass cls = Repository.lookupClass(callingClsName);
                    if (cls.instanceOf(throwableClass) && (stack.getStackDepth() > 0)) {
                        OpcodeStack.Item exItem = stack.getStackItem(0);
                        exMessageReg = exItem.getRegisterNumber();
                    }
                } else if (LOGGER_METHODS.contains(mthName)) {
                    checkForProblemsWithLoggerMethods();
                } else if (Values.TOSTRING.equals(mthName) && SignatureBuilder.SIG_VOID_TO_STRING.equals(getSigConstantOperand())) {
                    String callingClsName = getClassConstantOperand();
                    if (SignatureUtils.isPlainStringConvertableClass(callingClsName) && (stack.getStackDepth() > 0)) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        // if the stringbuilder was previously stored, don't report it
                        if (item.getRegisterNumber() < 0) {
                            seenMethodName = mthName;
                        }
                    }

                    if (seenMethodName == null) {
                        seenToString = true;
                    }
                }
            } else if (seen == Const.INVOKESPECIAL) {
                checkForLoggerParam();
            } else if (seen == Const.ANEWARRAY) {
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item sizeItem = stack.getStackItem(0);
                    Object con = sizeItem.getConstant();
                    if (con instanceof Integer) {
                        arraySize = (Integer) con;
                    }
                }
            } else if (seen == Const.AASTORE) {
                if (stack.getStackDepth() >= 3) {
                    OpcodeStack.Item arrayItem = stack.getStackItem(2);
                    LOUserValue<Integer> uv = (LOUserValue<Integer>) arrayItem.getUserValue();
                    if ((uv != null) && (uv.getType() == LOUserValue.LOType.ARRAY_SIZE)) {
                        Integer size = uv.getValue();
                        if ((size != null) && (size.intValue() > 0) && hasExceptionOnStack()) {
                            arrayItem.setUserValue(new LOUserValue<>(LOUserValue.LOType.ARRAY_SIZE, Integer.valueOf(-size.intValue())));
                        }
                    }
                }
            } else if (seen == Const.PUTSTATIC) {
                OpcodeStack.Item itm = stack.getStackItem(0);
                if (isStaticInitializer && isNonPrivateLogField(getClassConstantOperand(), getNameConstantOperand(), getSigConstantOperand())) {
                    XMethod m = itm.getReturnValueOf();
                    if ((m != null) && isLoggerWithClassParm(m)) {
                        bugReporter.reportBug(new BugInstance(this, BugType.LO_NON_PRIVATE_STATIC_LOGGER.name(), NORMAL_PRIORITY).addClass(this).addMethod(this)
                                .addSourceLine(this));
                    }
                }

                LOUserValue<Void> loggerUV = (LOUserValue<Void>) itm.getUserValue();
                if ((loggerUV != null) && (loggerUV.getType() == LOUserValue.LOType.FORMATTER_LOGGER)) {
                    formatterLoggers.add(getNameConstantOperand());
                }
            } else if (seen == Const.GETSTATIC) {
                if (formatterLoggers.contains(getNameConstantOperand())) {
                    seenFormatterLogger = true;
                }
            } else if (OpcodeUtils.isAStore(seen) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                LOUserValue<String> uv = (LOUserValue<String>) item.getUserValue();
                if (uv != null) {
                    if (((uv.getType() == LOUserValue.LOType.METHOD_NAME) && Values.TOSTRING.equals(uv.getValue()))
                            || (uv.getType() == LOUserValue.LOType.SIMPLE_FORMAT) || (uv.getType() == LOUserValue.LOType.TOSTRING)) {
                        item.setUserValue(new LOUserValue<>(LOUserValue.LOType.NULL, null));
                    }
                }
            }
        } catch (ClassNotFoundException cnfe) {
            bugReporter.reportMissingClass(cnfe);
        } finally {
            TernaryPatcher.pre(stack, seen);
            stack.sawOpcode(this, seen);
            TernaryPatcher.post(stack, seen);

            if (stack.getStackDepth() > 0) {
                OpcodeStack.Item item = stack.getStackItem(0);
                if (ldcClassName != null) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.CLASS_NAME, ldcClassName));
                } else if (seenMethodName != null) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.METHOD_NAME, seenMethodName));
                } else if (exMessageReg >= 0) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.MESSAGE_REG, Integer.valueOf(exMessageReg)));
                } else if (arraySize != null) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.ARRAY_SIZE, arraySize));
                } else if (simpleFormat) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.SIMPLE_FORMAT, Boolean.TRUE));
                } else if (seenToString) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.TOSTRING, null));
                } else if (seenFormatterLogger) {
                    item.setUserValue(new LOUserValue<>(LOUserValue.LOType.FORMATTER_LOGGER, null));
                }
            }
        }
    }
478600
@Override
    public void sawOpcode(int seen) {
        int groupId = -1;

        try {
            stack.precomputation(this);

            if (seen == Const.INVOKEINTERFACE) {
                String className = getClassConstantOperand();
                String methodName = getNameConstantOperand();
                String signature = getSigConstantOperand();
                QMethod methodInfo = new QMethod(methodName, signature);

                if (isCollection(className)) {
                    if (collectionMethods.contains(methodInfo) || ITERATOR.equals(methodInfo)) {
                        if (stack.getStackDepth() > 0) {
                            OpcodeStack.Item itm = stack.getStackItem(0);
                            groupId = findCollectionGroup(itm, true);
                        }
                    } else if (REMOVE.equals(methodInfo)) {
                        if (stack.getStackDepth() > 1) {
                            OpcodeStack.Item itm = stack.getStackItem(1);
                            int id = findCollectionGroup(itm, true);
                            if ((id >= 0) && collectionGroups.get(id).isStandardCollection()) {
                                Integer it = groupToIterator.get(Integer.valueOf(id));
                                Loop loop = loops.get(it);
                                if (loop != null) {
                                    int pc = getPC();
                                    if (loop.hasPC(pc)) {
                                        boolean needPop = !Values.SIG_VOID.equals(SignatureUtils.getReturnSignature(signature));

                                        if (!breakFollows(loop, needPop) && !returnFollows(needPop)) {
                                            bugReporter.reportBug(new BugInstance(this, BugType.DWI_DELETING_WHILE_ITERATING.name(), NORMAL_PRIORITY)
                                                    .addClass(this).addMethod(this).addSourceLine(this));
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        Integer numArgs = modifyingMethods.get(methodInfo);
                        if ((numArgs != null) && (stack.getStackDepth() > numArgs.intValue())) {
                            OpcodeStack.Item itm = stack.getStackItem(numArgs.intValue());
                            int id = findCollectionGroup(itm, true);
                            if (id >= 0) {
                                Integer it = groupToIterator.get(Integer.valueOf(id));
                                if (it != null) {
                                    Loop loop = loops.get(it);
                                    if (loop != null) {
                                        int pc = getPC();
                                        if (loop.hasPC(pc)) {
                                            boolean needPop = !Values.SIG_VOID.equals(SignatureUtils.getReturnSignature(signature));
                                            boolean breakFollows = breakFollows(loop, needPop);
                                            boolean returnFollows = !breakFollows && returnFollows(needPop);

                                            if (!breakFollows && !returnFollows) {
                                                bugReporter.reportBug(new BugInstance(this, BugType.DWI_MODIFYING_WHILE_ITERATING.name(), NORMAL_PRIORITY)
                                                        .addClass(this).addMethod(this).addSourceLine(this));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else if ("java/util/Iterator".equals(className) && HASNEXT.equals(methodInfo) && (stack.getStackDepth() > 0)) {
                    OpcodeStack.Item itm = stack.getStackItem(0);
                    Integer id = (Integer) itm.getUserValue();
                    if (id != null) {
                        groupId = id.intValue();
                    }
                }
            } else if ((seen == Const.PUTFIELD) || (seen == Const.PUTSTATIC)) {
                if (stack.getStackDepth() > 1) {
                    OpcodeStack.Item itm = stack.getStackItem(0);

                    Integer id = (Integer) itm.getUserValue();
                    if (id == null) {
                        FieldAnnotation fa = FieldAnnotation
                                .fromFieldDescriptor(new FieldDescriptor(getClassConstantOperand(), getNameConstantOperand(), getSigConstantOperand(), false));
                        itm = new OpcodeStack.Item(itm.getSignature(), fa, stack.getStackItem(1).getRegisterNumber());
                        removeFromCollectionGroup(itm);
                        groupId = findCollectionGroup(itm, true);
                    }
                }
            } else if (OpcodeUtils.isAStore(seen)) {
                if (stack.getStackDepth() > 0) {
                    OpcodeStack.Item itm = stack.getStackItem(0);
                    Integer id = (Integer) itm.getUserValue();
                    if (id != null) {
                        int reg = RegisterUtils.getAStoreReg(this, seen);

                        try {
                            JavaClass cls = itm.getJavaClass();
                            if ((cls != null) && cls.implementationOf(iteratorClass)) {
                                Integer regIt = Integer.valueOf(reg);
                                Iterator<Integer> curIt = groupToIterator.values().iterator();
                                while (curIt.hasNext()) {
                                    if (curIt.next().equals(regIt)) {
                                        curIt.remove();
                                    }
                                }
                                groupToIterator.put(id, regIt);
                            }

                            GroupPair pair = collectionGroups.get(id.intValue());
                            if (pair != null) {
                                pair.addMember(Integer.valueOf(reg));
                            }
                        } catch (ClassNotFoundException cnfe) {
                            bugReporter.reportMissingClass(cnfe);
                        }
                    } else {
                        String cls = itm.getSignature();
                        if ((cls != null) && cls.startsWith(Values.SIG_QUALIFIED_CLASS_PREFIX)) {
                            cls = SignatureUtils.trimSignature(cls);
                            if (isCollection(cls) || "java/util/Iterator".equals(cls)) {
                                int reg = RegisterUtils.getAStoreReg(this, seen);
                                removeFromCollectionGroup(new OpcodeStack.Item(itm, reg));
                                Iterator<Integer> it = groupToIterator.values().iterator();
                                while (it.hasNext()) {
                                    if (it.next().intValue() == reg) {
                                        it.remove();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            } else if (OpcodeUtils.isALoad(seen)) {
                int reg = RegisterUtils.getALoadReg(this, seen);
                OpcodeStack.Item itm = new OpcodeStack.Item(new OpcodeStack.Item(), reg);
                groupId = findCollectionGroup(itm, false);
            } else if ((seen == Const.IFEQ) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item itm = stack.getStackItem(0);
                Integer id = (Integer) itm.getUserValue();
                if (id != null) {
                    int target = getBranchTarget();
                    int gotoAddr = target - 3;
                    int ins = getCode().getCode()[gotoAddr];
                    if (ins < 0) {
                        ins = 256 + ins;
                    }
                    if ((ins == Const.GOTO) || (ins == Const.GOTO_W)) {
                        Integer reg = groupToIterator.get(id);
                        if (reg != null) {
                            loops.put(reg, new Loop(getPC(), gotoAddr));
                        }
                    }
                }
            }
        } finally {
            TernaryPatcher.pre(stack, seen);
            stack.sawOpcode(this, seen);
            TernaryPatcher.post(stack, seen);
            if ((groupId >= 0) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item itm = stack.getStackItem(0);
                itm.setUserValue(Integer.valueOf(groupId));
            }

            processEndOfScopes(Integer.valueOf(getPC()));
        }
    }
931751
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            if ((seen == Const.INVOKEVIRTUAL) || (seen == Const.INVOKEINTERFACE)) {
                String clsName = getClassConstantOperand();
                String methodName = getNameConstantOperand();
                String signature = getSigConstantOperand();

                if ("add".equals(methodName) && SignatureBuilder.SIG_OBJECT_TO_BOOLEAN.equals(signature) && isImplementationOf(clsName, setCls)) {
                    if (stack.getStackDepth() > 1) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        JavaClass entryCls = item.getJavaClass();
                        if (isImplementationOf(entryCls, collectionCls)) {
                            bugReporter.reportBug(new BugInstance(this, BugType.DSOC_DUBIOUS_SET_OF_COLLECTIONS.name(), NORMAL_PRIORITY).addClass(this)
                                    .addMethod(this).addSourceLine(this));
                        }
                    }
                } else if ("put".equals(methodName) && SignatureBuilder.SIG_TWO_OBJECTS_TO_OBJECT.equals(signature) && isImplementationOf(clsName, setCls)
                        && (stack.getStackDepth() > 2)) {
                    OpcodeStack.Item item = stack.getStackItem(1);
                    JavaClass entryCls = item.getJavaClass();
                    if (isImplementationOf(entryCls, collectionCls)) {
                        bugReporter.reportBug(new BugInstance(this, BugType.DSOC_DUBIOUS_SET_OF_COLLECTIONS.name(), NORMAL_PRIORITY).addClass(this)
                                .addMethod(this).addSourceLine(this));
                    }
                }
            }
        } catch (ClassNotFoundException cnfe) {
            bugReporter.reportMissingClass(cnfe);
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
1230602
@Override
    public void sawOpcode(int seen) {
        Units unit = null;
        try {
            stack.precomputation(this);

            switch (seen) {
                case Const.INVOKEVIRTUAL:
                case Const.INVOKEINTERFACE:
                case Const.INVOKESTATIC:
                    unit = processInvoke();
                break;

                case Const.GETSTATIC:
                    String clsName = getClassConstantOperand();
                    if ("java/util/concurrent/TimeUnit".equals(clsName) || "edu/emory/matchcs/backport/java/util/concurrent/TimeUnit".equals(clsName)) {
                        unit = TIMEUNIT_TO_UNITS.get(getNameConstantOperand());
                    }
                break;

                case Const.L2I:
                case Const.I2L:
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        unit = (Units) item.getUserValue();
                    }
                break;

                case Const.IADD:
                case Const.ISUB:
                case Const.IMUL:
                case Const.IDIV:
                case Const.IREM:
                case Const.LADD:
                case Const.LSUB:
                case Const.LMUL:
                case Const.LDIV:
                case Const.LREM:
                    processArithmetic();
                break;

                default:
                break;
            }
        } finally {
            stack.sawOpcode(this, seen);
            if ((unit != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item item = stack.getStackItem(0);
                item.setUserValue(unit);
            }
        }
    }
286775
@Override
    public void sawOpcode(int seen) {
        Integer userValue = null;
        try {
            stack.precomputation(this);

            switch (seen) {
                case Const.NEWARRAY:
                case Const.ANEWARRAY: {
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item itm = stack.getStackItem(0);
                        Integer size = (Integer) itm.getConstant();
                        if ((size != null) && (size.intValue() == 1)) {
                            userValue = Values.NEGATIVE_ONE;
                        }
                    }
                }
                break;

                case Const.IASTORE:
                case Const.LASTORE:
                case Const.FASTORE:
                case Const.DASTORE:
                case Const.AASTORE:
                case Const.BASTORE:
                case Const.CASTORE:
                case Const.SASTORE: {
                    userValue = processArrayElementStore();
                }
                break;

                case Const.ASTORE:
                case Const.ASTORE_0:
                case Const.ASTORE_1:
                case Const.ASTORE_2:
                case Const.ASTORE_3: {
                    processLocalStore(seen);
                }
                break;

                case Const.INVOKEVIRTUAL:
                case Const.INVOKEINTERFACE:
                case Const.INVOKESPECIAL:
                case Const.INVOKESTATIC: {
                    processMethodCall();
                }
                break;

                case Const.IALOAD:
                case Const.LALOAD:
                case Const.FALOAD:
                case Const.DALOAD:
                case Const.AALOAD:
                case Const.BALOAD:
                case Const.CALOAD:
                case Const.SALOAD: {
                    if (stack.getStackDepth() >= 2) {
                        OpcodeStack.Item arItm = stack.getStackItem(1);
                        int arReg = arItm.getRegisterNumber();
                        WrapperInfo wi = wrappers.get(Integer.valueOf(arReg));
                        if ((wi != null) && wi.wasArg) {
                            userValue = Integer.valueOf(wi.wrappedReg);
                        }
                    }
                }
                break;

                case Const.ALOAD:
                case Const.ALOAD_0:
                case Const.ALOAD_1:
                case Const.ALOAD_2:
                case Const.ALOAD_3: {
                    int reg = RegisterUtils.getALoadReg(this, seen);
                    WrapperInfo wi = wrappers.get(Integer.valueOf(reg));
                    if (wi != null) {
                        userValue = Integer.valueOf(wi.wrappedReg);
                    }
                }
                break;

                case Const.ISTORE:
                case Const.ISTORE_0:
                case Const.ISTORE_1:
                case Const.ISTORE_2:
                case Const.ISTORE_3:
                case Const.LSTORE:
                case Const.LSTORE_0:
                case Const.LSTORE_1:
                case Const.LSTORE_2:
                case Const.LSTORE_3:
                case Const.DSTORE:
                case Const.DSTORE_0:
                case Const.DSTORE_1:
                case Const.DSTORE_2:
                case Const.DSTORE_3:
                case Const.FSTORE:
                case Const.FSTORE_0:
                case Const.FSTORE_1:
                case Const.FSTORE_2:
                case Const.FSTORE_3: {
                    if (stack.getStackDepth() == 0) {
                        break;
                    }
                    OpcodeStack.Item itm = stack.getStackItem(0);
                    Integer elReg = (Integer) itm.getUserValue();
                    if (elReg == null) {
                        break;
                    }
                    int reg = RegisterUtils.getStoreReg(this, seen);
                    if (elReg.intValue() == reg) {
                        bugReporter.reportBug(new BugInstance(this, BugType.AWCBR_ARRAY_WRAPPED_CALL_BY_REFERENCE.name(), NORMAL_PRIORITY).addClass(this)
                                .addMethod(this).addSourceLine(this));
                    }
                }
                break;

                default:
                break;
            }
        } finally {
            TernaryPatcher.pre(stack, seen);
            stack.sawOpcode(this, seen);
            TernaryPatcher.post(stack, seen);
            if ((userValue != null) && (stack.getStackDepth() > 0)) {
                OpcodeStack.Item itm = stack.getStackItem(0);
                itm.setUserValue(userValue);
            }
        }
    }
129885
@Override
    public void sawOpcode(int seen) {
        if ((seen == Const.GETFIELD) || (seen == Const.PUTFIELD)) {
            String fieldName = getNameConstantOperand();
            FieldInfo fi = localizableFields.get(fieldName);
            if (fi != null) {
                SourceLineAnnotation sla = SourceLineAnnotation.fromVisitedInstruction(this);
                fi.setSrcLineAnnotation(sla);
            }
        }
    }
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);
            }
        }
    }
268364
@Override
    public void sawOpcode(final int seen) {
        if (stage == Stage.FIND_LOOP_STAGE) {
            sawOpcodeLoop(seen);
        } else {
            sawOpcodeBug(seen);
        }
    }
422575
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            if ((seen != Const.INVOKEVIRTUAL) || !"wait".equals(getNameConstantOperand()) || stack.getStackDepth() == 0) {
                return;
            }
            JavaClass cls = stack.getStackItem(0).getJavaClass();
            if (cls != null) {
                String clsName = cls.getClassName();
                if (concurrentAwaitClasses.contains(clsName)) {
                    bugReporter.reportBug(new BugInstance(this, BugType.SWCO_SUSPICIOUS_WAIT_ON_CONCURRENT_OBJECT.name(), NORMAL_PRIORITY).addClass(this)
                            .addMethod(this).addSourceLine(this));
                }
            }
        } catch (ClassNotFoundException cnfe) {
            bugReporter.reportMissingClass(cnfe);
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
268794
@Override
	public void sawOpcode(final int seen) {
		try {
			stack.precomputation(this);

			if (seen == Const.INVOKEINTERFACE) {
				processInvokeInterface();
			} else if (seen == Const.INVOKEVIRTUAL) {
				processInvokeVirtual();
			} else if ((seen == Const.ARETURN) && (stack.getStackDepth() > 0)) {
				OpcodeStack.Item item = stack.getStackItem(0);
				XField field = item.getXField();
				if (field != null) {
					String fieldName = field.getName();
					fieldsReported.remove(fieldName);
					if (fieldsReported.isEmpty()) {
						throw new StopOpcodeParsingException();
					}
				}
			}
		} finally {
			stack.sawOpcode(this, seen);
		}
	}
630229
@Override
    public void sawOpcode(int seen) {
        if (seenReturn && seenTransferOfControl && seenStateChange) {
            return;
        }

        if (DEBUG) {
            System.out.println(stack);
            System.out.println(getPC() + " : " + Const.getOpcodeName(seen));
        }

        if ((seen == Const.INVOKEVIRTUAL || seen == Const.INVOKEINTERFACE) && "add".equals(getNameConstantOperand())
                && "(Ljava/lang/Object;)Z".equals(getSigConstantOperand()) && stack.getStackDepth() >= 2) {
            OpcodeStack.Item it0 = stack.getStackItem(0);
            int r0 = it0.getRegisterNumber();
            OpcodeStack.Item it1 = stack.getStackItem(1);
            int r1 = it1.getRegisterNumber();
            if (r0 == r1 && r0 > 0) {
                bugReporter.reportBug(new BugInstance(this, "IL_CONTAINER_ADDED_TO_ITSELF", NORMAL_PRIORITY).addClassAndMethod(
                        this).addSourceLine(this));
            }
        }

        if ((seen == Const.INVOKEVIRTUAL || seen == Const.INVOKESPECIAL || seen == Const.INVOKEINTERFACE || seen == Const.INVOKESTATIC)
                && getNameConstantOperand().equals(getMethodName())
                && getSigConstantOperand().equals(getMethodSig())
                && (seen == Const.INVOKESTATIC) == getMethod().isStatic()
                && (seen == Const.INVOKESPECIAL) == (getMethod().isPrivate() && !getMethod().isStatic() || Const.CONSTRUCTOR_NAME.equals(getMethodName()))) {
            Type arguments[] = getMethod().getArgumentTypes();
            // stack.getStackDepth() >= parameters
            int parameters = arguments.length;
            if (!getMethod().isStatic()) {
                parameters++;
            }
            XMethod xMethod = XFactory.createReferencedXMethod(this);
            if (DEBUG) {
                System.out.println("IL: Checking...");
                System.out.println(xMethod);
                System.out.println("vs. " + getClassName() + "." + getMethodName() + " : " + getMethodSig());

            }
            if (xMethod.getClassName().replace('.', '/').equals(getClassName()) || seen == Const.INVOKEINTERFACE) {
                // Invocation of same method
                // Now need to see if parameters are the same
                int firstParameter = 0;
                if (Const.CONSTRUCTOR_NAME.equals(getMethodName())) {
                    firstParameter = 1;
                }

                // match1 should be true if it is any call to the exact same
                // method
                // and no state has been change.
                // if match1 is true, the method may not always perform
                // a recursive infinite loop, but this particular method call is
                // an infinite
                // recursive loop

                boolean match1 = !seenStateChange;
                for (int i = firstParameter; match1 && i < parameters; i++) {
                    OpcodeStack.Item it = stack.getStackItem(parameters - 1 - i);
                    if (!it.isInitialParameter() || it.getRegisterNumber() != i) {
                        match1 = false;
                    }
                }

                boolean sameMethod = seen == Const.INVOKESTATIC || Const.CONSTRUCTOR_NAME.equals(getNameConstantOperand());
                if (!sameMethod) {
                    // Have to check if first parmeter is the same
                    // know there must be a this argument
                    if (DEBUG) {
                        System.out.println("Stack is " + stack);
                    }
                    OpcodeStack.Item p = stack.getStackItem(parameters - 1);
                    if (DEBUG) {
                        System.out.println("parameters = " + parameters + ", Item is " + p);
                    }
                    String sig = p.getSignature();
                    sameMethod = p.isInitialParameter() && p.getRegisterNumber() == 0 && sig.equals("L" + getClassName() + ";");

                }

                // match2 and match3 are two different ways of seeing if the
                // call site
                // postdominates the method entry.

                // technically, we use (!seenTransferOfControl || !seenReturn &&
                // largestBranchTarget < getPC())
                // as a check that the call site postdominates the method entry.
                // If those are true,
                // and sameMethod is true, we have a guaranteed IL.

                boolean match2 = sameMethod && !seenTransferOfControl;
                boolean match3 = sameMethod && !seenReturn && largestBranchTarget < getPC();
                if (match1 || match2 || match3) {
                    if (DEBUG) {
                        System.out.println("IL: " + sameMethod + " " + match1 + " " + match2 + " " + match3);
                    }
                    //                    int priority = HIGH_PRIORITY;
                    //                    if (!match1 && !match2 && seenThrow)
                    //                        priority = NORMAL_PRIORITY;
                    //                    if (seen == Const.INVOKEINTERFACE)
                    //                        priority = NORMAL_PRIORITY;
                    bugReporter.reportBug(new BugInstance(this, "IL_INFINITE_RECURSIVE_LOOP", HIGH_PRIORITY).addClassAndMethod(
                            this).addSourceLine(this));
                }
            }
        }

        switch (seen) {
        case Const.ARETURN:
        case Const.IRETURN:
        case Const.LRETURN:
        case Const.RETURN:
        case Const.DRETURN:
        case Const.FRETURN:
            seenReturn = true;
            seenTransferOfControl = true;
            break;
        case Const.ATHROW:
            //            seenThrow = true;
            seenTransferOfControl = true;
            break;
        case Const.PUTSTATIC:
        case Const.PUTFIELD:
        case Const.IASTORE:
        case Const.AASTORE:
        case Const.DASTORE:
        case Const.FASTORE:
        case Const.LASTORE:
        case Const.SASTORE:
        case Const.CASTORE:
        case Const.BASTORE:
            seenStateChange = true;
            break;
        case Const.INVOKEVIRTUAL:
        case Const.INVOKESPECIAL:
        case Const.INVOKEINTERFACE:
        case Const.INVOKESTATIC:
            if ("print".equals(getNameConstantOperand()) || "println".equals(getNameConstantOperand())
                    || "log".equals(getNameConstantOperand()) || "toString".equals(getNameConstantOperand())) {
                break;
            }
            seenStateChange = true;
            break;
        default:
            break;
        }
    }
1267373
@Override
    public void sawOpcode(int seen) {
        FQMethod curCalledMethod = null;
        Boolean sawPlainOptional = null;

        try {
            switch (seen) {
                case Const.IFNULL:
                case Const.IFNONNULL:
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item itm = stack.getStackItem(0);
                        if (OPTIONAL_CLASSES.contains(itm.getSignature())) {
                            bugReporter.reportBug(new BugInstance(this, BugType.OI_OPTIONAL_ISSUES_CHECKING_REFERENCE.name(), NORMAL_PRIORITY).addClass(this)
                                    .addMethod(this).addSourceLine(this));
                        }

                    }
                break;

                case Const.INVOKEDYNAMIC:
                    // smells like a hack. Not sure how to do this better
                    ConstantInvokeDynamic id = (ConstantInvokeDynamic) getConstantRefOperand();
                    ConstantPool cp = getConstantPool();
                    ConstantNameAndType nameAndType = (ConstantNameAndType) cp.getConstant(id.getNameAndTypeIndex());
                    ConstantUtf8 typeConstant = (ConstantUtf8) cp.getConstant(nameAndType.getSignatureIndex());
                    curCalledMethod = new FQMethod(getClassName(), "lambda$" + id.getBootstrapMethodAttrIndex(), typeConstant.getBytes());
                break;

                case Const.INVOKESTATIC:
                case Const.INVOKEINTERFACE:
                case Const.INVOKESPECIAL:
                    String clsName = getClassConstantOperand();
                    String methodName = getNameConstantOperand();
                    curCalledMethod = new FQMethod(clsName, methodName, getSigConstantOperand());

                    if ("java/util/Optional".equals(clsName) && "of".equals(methodName)) {
                        if (stack.getStackDepth() > 0) {
                            OpcodeStack.Item itm = stack.getStackItem(0);
                            String itmSig = itm.getSignature();
                            if (BOXED_OPTIONAL_TYPES.contains(itmSig)) {
                                bugReporter.reportBug(new BugInstance(this, BugType.OI_OPTIONAL_ISSUES_PRIMITIVE_VARIANT_PREFERRED.name(), LOW_PRIORITY)
                                        .addClass(this).addMethod(this).addSourceLine(this));
                            }
                        }
                    }
                break;

                case Const.INVOKEVIRTUAL:
                    curCalledMethod = new FQMethod(getClassConstantOperand(), getNameConstantOperand(), getSigConstantOperand());
                    if (OR_ELSE_METHODS.contains(curCalledMethod)) {
                        if (stack.getStackDepth() > 0) {
                            OpcodeStack.Item itm = stack.getStackItem(0);
                            if ((itm.getRegisterNumber() < 0) && (itm.getReturnValueOf() != null) && !isTrivialStackOps()) {
                                bugReporter.reportBug(new BugInstance(this, BugType.OI_OPTIONAL_ISSUES_USES_IMMEDIATE_EXECUTION.name(), NORMAL_PRIORITY)
                                        .addClass(this).addMethod(this).addSourceLine(this));
                            }
                        }
                        if (OPTIONAL_OR_ELSE_METHOD.equals(curCalledMethod)) {
                            sawPlainOptional = Boolean.TRUE;
                        }
                    } else if (OR_ELSE_GET_METHODS.contains(curCalledMethod)) {
                        if (!activeStackOps.isEmpty()) {
                            ActiveStackOp op = activeStackOps.getLast();

                            FQMethod method = op.getMethod();
                            if (method == null) {
                                bugReporter.reportBug(new BugInstance(this, BugType.OI_OPTIONAL_ISSUES_USES_ORELSEGET_WITH_NULL.name(), LOW_PRIORITY)
                                        .addClass(this).addMethod(this).addSourceLine(this));
                            } else {
                                Method getMethod = getLambdaMethod(method.getMethodName());
                                if (getMethod != null) {
                                    byte[] byteCode = getMethod.getCode().getCode();
                                    if (byteCode.length <= 4) {
                                        // we are looking for ALOAD, GETFIELD, or LDC followed by ARETURN, that should fit in 4 bytes
                                        if (!hasInvoke(byteCode)) {
                                            bugReporter.reportBug(new BugInstance(this, BugType.OI_OPTIONAL_ISSUES_USES_DELAYED_EXECUTION.name(), LOW_PRIORITY)
                                                    .addClass(this).addMethod(this).addSourceLine(this));
                                        }
                                    }
                                }
                            }
                        }
                        if (OPTIONAL_OR_ELSE_GET_METHOD.equals(curCalledMethod)) {
                            sawPlainOptional = Boolean.TRUE;
                        }
                    } else if (OPTIONAL_GET_METHOD.equals(curCalledMethod)) {
                        sawPlainOptional = Boolean.TRUE;
                    }
                break;
            }
        } finally {
            stack.sawOpcode(this, seen);
            int stackDepth = stack.getStackDepth();
            if (stackDepth == 0) {
                activeStackOps.clear();
            } else {
                activeStackOps.addLast(new ActiveStackOp(seen, curCalledMethod));
                while (activeStackOps.size() > stackDepth) {
                    activeStackOps.removeFirst();
                }
                if (sawPlainOptional != null) {
                    OpcodeStack.Item itm = stack.getStackItem(0);
                    itm.setUserValue(sawPlainOptional);
                }
            }
        }
    }
753132
@Override
    public void sawOpcode(int seen) {
        if (downwardBranchTarget == -1) {
            switch (state) {
                case SAW_NOTHING:
                    sawOpcodeAfterNothing(seen);
                break;

                case SAW_LOAD:
                    sawOpcodeAfterLoad(seen);
                break;

                case SAW_CHECKCAST:
                    sawOpcodeAfterCheckCast(seen);
                break;
            }

            int insTarget = -1;
            if (((seen >= Const.IFEQ) && (seen <= Const.IF_ACMPNE)) || (seen == Const.GOTO) || (seen == Const.GOTO_W)) {
                insTarget = getBranchTarget();
                if (insTarget < getPC()) {
                    insTarget = -1;
                }
            } else if ((seen == Const.LOOKUPSWITCH) || (seen == Const.TABLESWITCH)) {
                insTarget = this.getDefaultSwitchOffset() + getPC();
            }

            if (insTarget > downwardBranchTarget) {
                downwardBranchTarget = insTarget;
            }
        } else {
            state = State.SAW_NOTHING;
            if (getPC() >= downwardBranchTarget) {
                downwardBranchTarget = -1;
            }
        }
    }
715349
@Override
    public void sawOpcode(int seen) {
        switch (state) {
            case SEEN_NOTHING:
                if ((seen == Const.INVOKEINTERFACE) || (seen == Const.INVOKEVIRTUAL)) {
                    String sig = getSigConstantOperand();
                    String returnSig = SignatureUtils.getReturnSignature(sig);
                    if (returnSig.startsWith(Values.SIG_QUALIFIED_CLASS_PREFIX)) {
                        String clsName = getClassConstantOperand();
                        if (!Values.SLASHED_JAVA_LANG_OBJECT.equals(clsName) && !Values.SLASHED_JAVA_LANG_CLASS.equals(clsName)) {
                            returnType = SignatureUtils.trimSignature(returnSig);
                            invokePC = getPC();
                            state = State.SEEN_INVOKE;
                        }
                    }
                }
            break;

            case SEEN_INVOKE:
                if (seen == Const.POP) {
                    state = State.SEEN_POP;
                } else {
                    state = State.SEEN_NOTHING;
                    returnType = null;
                }
            break;

            case SEEN_POP:
                if (((seen >= Const.ACONST_NULL) && (seen <= Const.DCONST_1)) || (seen == Const.GETFIELD)) {
                    state = State.SEEN_POP;
                } else if ((seen == Const.INVOKESTATIC) || (seen == Const.GETSTATIC)) {
                    if (getClassConstantOperand().equals(returnType) && (lnTable.getSourceLine(invokePC) == lnTable.getSourceLine(getPC()))) {
                        bugReporter.reportBug(new BugInstance(this, BugType.NIR_NEEDLESS_INSTANCE_RETRIEVAL.name(), NORMAL_PRIORITY).addClass(this)
                                .addMethod(this).addSourceLine(this));
                    }
                    state = State.SEEN_NOTHING;
                    returnType = null;
                } else {
                    state = State.SEEN_NOTHING;
                    returnType = null;
                }
            break;

            default:
                state = State.SEEN_NOTHING;
                returnType = null;
            break;
        }
    }
546778
@Override
    public void sawOpcode(int seen) {
        try {
            stack.precomputation(this);

            switch (seen) {
                case Const.IRETURN: {
                    processIntegerReturn();
                }
                break;

                case Const.GOTO:
                case Const.GOTO_W: {
                    if (stack.getStackDepth() > 0) {
                        throw new StopOpcodeParsingException();
                    }
                    if (furthestBranchTarget < getBranchTarget()) {
                        furthestBranchTarget = getBranchTarget();
                    }
                }
                break;

                case Const.IFEQ:
                case Const.IFNE:
                case Const.IFLT:
                case Const.IFGE:
                case Const.IFGT:
                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.IFNULL:
                case Const.IFNONNULL: {
                    if (furthestBranchTarget < getBranchTarget()) {
                        furthestBranchTarget = getBranchTarget();
                    }
                }
                break;

                case Const.LOOKUPSWITCH:
                case Const.TABLESWITCH: {
                    int defTarget = getDefaultSwitchOffset() + getPC();
                    if (furthestBranchTarget > defTarget) {
                        furthestBranchTarget = defTarget;
                    }
                }
                break;

                case Const.ATHROW: {
                    if (stack.getStackDepth() > 0) {
                        OpcodeStack.Item item = stack.getStackItem(0);
                        String exSig = item.getSignature();
                        if ("Ljava/lang/UnsupportedOperationException;".equals(exSig)) {
                            throw new StopOpcodeParsingException();
                        }
                    }
                }
                break;

                /*
                 * these three opcodes are here because findbugs proper is broken, it sometimes
                 * doesn't push this constant on the stack, because of bad branch handling
                 */
                case Const.ICONST_0:
                    if (getNextOpcode() == Const.IRETURN) {
                        sawConstant = Integer.valueOf(0);
                    }
                break;

                case Const.ICONST_M1:
                    if (getNextOpcode() == Const.IRETURN) {
                        sawConstant = Integer.valueOf(-1);
                    }
                break;

                case Const.ICONST_1:
                    if (getNextOpcode() == Const.IRETURN) {
                        sawConstant = Integer.valueOf(1);
                    }
                break;

                default:
                break;

            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }
635270
@Override
    public void sawOpcode(int seen) {
        boolean processed = false;
        Iterator<IfStatement> isi = ifStatements.iterator();
        while (isi.hasNext()) {
            IfStatement.Action action = isi.next().processOpcode(this, bugReporter, seen);
            if (action == IfStatement.Action.REMOVE_ACTION) {
                isi.remove();
            } else if (action == IfStatement.Action.PROCESSED_ACTION) {
                processed = true;
            }
        }

        if (!processed && OpcodeUtils.isALoad(seen)) {
            IfStatement is = new IfStatement(this, seen);
            ifStatements.add(is);
        }
    }
1272194
@Override
    public void sawOpcode(final int seen) {
        try {
            stack.precomputation(this);

            if (OpcodeUtils.isStandardInvoke(seen)) {
                String calledClass = getDottedClassConstantOperand();

                if (seen == Const.INVOKEINTERFACE) {
                    int parmCount = SignatureUtils.getNumParameters(this.getSigConstantOperand());
                    if (!countClassAccess(parmCount)) {
                        countClassAccess(calledClass);
                    }
                } else {
                    countClassAccess(calledClass);
                }
            } else if (seen == Const.PUTFIELD) {
                countClassAccess(1);
            } else if (seen == Const.GETFIELD) {
                countClassAccess(0);
            } else if ((seen == Const.PUTSTATIC) || (seen == Const.GETSTATIC)) {
                countClassAccess(getDottedClassConstantOperand());
            } else if ((seen == Const.ALOAD_0) && (!methodIsStatic)) {
                countClassAccess(clsName);
            }
        } finally {
            stack.sawOpcode(this, seen);
        }
    }