@ Override public void sawOpcode ( int seen ) { boolean srcField = false ; try { stack . precomputation ( this ) ; switch ( seen ) { case Const . ALOAD_0 : srcField = true ; break ; case Const . DUP : if ( stack . getStackDepth ( ) > 0 ) { OpcodeStack . Item item = stack . getStackItem ( 0 ) ; if ( item . getUserValue ( ) != null ) { srcField = true ; } } break ; case Const . GETFIELD : if ( stack . getStackDepth ( ) > 0 ) { OpcodeStack . Item item = stack . getStackItem ( 0 ) ; if ( item . getRegisterNumber ( ) == 0 ) { srcField = true ; } } break ; case Const . PUTFIELD : if ( stack . getStackDepth ( ) >= 2 ) { OpcodeStack . Item item = stack . getStackItem ( 1 ) ; if ( ( item . getRegisterNumber ( ) == 0 ) || ( item . getUserValue ( ) != null ) ) { bugReporter . reportBug ( new BugInstance ( this , BugType . SCA_SUSPICIOUS_CLONE_ALGORITHM . name ( ) , NORMAL_PRIORITY ) . addClass ( this ) . addMethod ( this ) . addSourceLine ( this ) ) ; } } break ; case Const . INVOKEINTERFACE : case Const . INVOKEVIRTUAL : String sig = getSigConstantOperand ( ) ; int numArgs = SignatureUtils . getNumParameters ( sig ) ; if ( stack . getStackDepth ( ) > numArgs ) { OpcodeStack . Item item = stack . getStackItem ( numArgs ) ; if ( ( item . getRegisterNumber ( ) == 0 ) || ( item . getUserValue ( ) != null ) ) { String name = getNameConstantOperand ( ) ; Integer priority = changingMethods . get ( name ) ; if ( priority != null ) { bugReporter . reportBug ( new BugInstance ( this , BugType . SCA_SUSPICIOUS_CLONE_ALGORITHM . name ( ) , priority . intValue ( ) ) . addClass ( this ) . addMethod ( this ) . addSourceLine ( this ) ) ; } } } break ; default : break ; } } finally { TernaryPatcher . pre ( stack , seen ) ; stack . sawOpcode ( this , seen ) ; TernaryPatcher . post ( stack , seen ) ; if ( srcField && ( stack . getStackDepth ( ) > 0 ) ) { OpcodeStack . Item item = stack . getStackItem ( 0 ) ; item . setUserValue ( Boolean . TRUE ) ; } } }
override the visitor to look for stores to member fields of the source object on a clone