@@ -185,15 +185,54 @@ class OperandNode extends Node, TOperandNode {
185185 override string toString ( ) { result = this .getOperand ( ) .toString ( ) }
186186}
187187
188+ /** An abstract class that defines conversion-like instructions. */
189+ abstract private class SkippableInstruction extends Instruction {
190+ abstract Instruction getSourceInstruction ( ) ;
191+ }
192+
193+ /**
194+ * Gets the instruction that is propaged through a non-empty sequence of conversion-like instructions.
195+ */
196+ private Instruction skipSkippableInstructionsRec ( SkippableInstruction skip ) {
197+ result = skip .getSourceInstruction ( ) and not result instanceof SkippableInstruction
198+ or
199+ result = skipSkippableInstructionsRec ( skip .getSourceInstruction ( ) )
200+ }
201+
202+ /**
203+ * Gets the instruction that is propagated through a (possibly empty) sequence of conversion-like
204+ * instructions.
205+ */
206+ private Instruction skipSkippableInstructions ( Instruction instr ) {
207+ result = instr and not result instanceof SkippableInstruction
208+ or
209+ result = skipSkippableInstructionsRec ( instr )
210+ }
211+
212+ private class SkippableCopyValueInstruction extends SkippableInstruction , CopyValueInstruction {
213+ override Instruction getSourceInstruction ( ) { result = this .getSourceValue ( ) }
214+ }
215+
216+ private class SkippableConvertInstruction extends SkippableInstruction , ConvertInstruction {
217+ override Instruction getSourceInstruction ( ) { result = this .getUnary ( ) }
218+ }
219+
220+ private class SkippableCheckedConvertInstruction extends SkippableInstruction ,
221+ CheckedConvertOrNullInstruction {
222+ override Instruction getSourceInstruction ( ) { result = this .getUnary ( ) }
223+ }
224+
225+ private class SkippableInheritanceConversionInstruction extends SkippableInstruction ,
226+ InheritanceConversionInstruction {
227+ override Instruction getSourceInstruction ( ) { result = this .getUnary ( ) }
228+ }
229+
188230/**
189231 * INTERNAL: do not use. Gets the `FieldNode` corresponding to `instr`, if
190232 * `instr` is an instruction that propagates an address of a `FieldAddressInstruction`.
191233 */
192234FieldNode getFieldNodeForFieldInstruction ( Instruction instr ) {
193- result .getFieldInstruction ( ) =
194- any ( FieldAddressInstruction fai |
195- longestRegisterInstructionOperandLocalFlowStep ( instructionNode ( fai ) , instructionNode ( instr ) )
196- )
235+ result .getFieldInstruction ( ) = skipSkippableInstructions ( instr )
197236}
198237
199238/**
@@ -584,11 +623,6 @@ class VariableNode extends Node, TVariableNode {
584623 */
585624InstructionNode instructionNode ( Instruction instr ) { result .getInstruction ( ) = instr }
586625
587- /**
588- * Gets the node corresponding to `operand`.
589- */
590- OperandNode operandNode ( Operand operand ) { result .getOperand ( ) = operand }
591-
592626/**
593627 * DEPRECATED: use `definitionByReferenceNodeFromArgument` instead.
594628 *
@@ -706,47 +740,6 @@ private predicate flowIntoReadNode(Node nodeFrom, FieldNode nodeTo) {
706740 )
707741}
708742
709- /** Holds if `node` holds an `Instruction` or `Operand` that has a register result. */
710- private predicate hasRegisterResult ( Node node ) {
711- node .asOperand ( ) instanceof RegisterOperand
712- or
713- exists ( Instruction i | i = node .asInstruction ( ) and not i .hasMemoryResult ( ) )
714- }
715-
716- /**
717- * Holds if there is a `Instruction` or `Operand` flow step from `nodeFrom` to `nodeTo` and both
718- * `nodeFrom` and `nodeTo` wraps register results.
719- */
720- private predicate registerInstructionOperandLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
721- hasRegisterResult ( nodeFrom ) and
722- hasRegisterResult ( nodeTo ) and
723- instructionOperandLocalFlowStep ( nodeFrom , nodeTo )
724- }
725-
726- /**
727- * INTERNAL: do not use.
728- * Holds if `nodeFrom` has no incoming local `Operand` or `Instruction` register flow and `nodeFrom` can
729- * reach `nodeTo` using only local `Instruction` or `Operand` register flow steps.
730- */
731- bindingset [ nodeTo]
732- private predicate longestRegisterInstructionOperandLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
733- registerInstructionOperandLocalFlowStep * ( nodeFrom , nodeTo ) and
734- not registerInstructionOperandLocalFlowStep ( _, nodeFrom )
735- }
736-
737- /**
738- * INTERNAL: do not use.
739- * Holds if `nodeFrom` is an operand and `nodeTo` is an instruction node that uses this operand, or
740- * if `nodeFrom` is an instruction and `nodeTo` is an operand that refers to this instruction.
741- */
742- private predicate instructionOperandLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
743- // Operand -> Instruction flow
744- simpleInstructionLocalFlowStep ( nodeFrom .asOperand ( ) , nodeTo .asInstruction ( ) )
745- or
746- // Instruction -> Operand flow
747- simpleOperandLocalFlowStep ( nodeFrom .asInstruction ( ) , nodeTo .asOperand ( ) )
748- }
749-
750743/**
751744 * INTERNAL: do not use.
752745 *
@@ -755,7 +748,11 @@ private predicate instructionOperandLocalFlowStep(Node nodeFrom, Node nodeTo) {
755748 */
756749cached
757750predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
758- instructionOperandLocalFlowStep ( nodeFrom , nodeTo )
751+ // Operand -> Instruction flow
752+ simpleInstructionLocalFlowStep ( nodeFrom .asOperand ( ) , nodeTo .asInstruction ( ) )
753+ or
754+ // Instruction -> Operand flow
755+ simpleOperandLocalFlowStep ( nodeFrom .asInstruction ( ) , nodeTo .asOperand ( ) )
759756 or
760757 flowIntoReadNode ( nodeFrom , nodeTo )
761758 or
0 commit comments