@@ -56,6 +56,32 @@ class ControlFlowNode extends @cil_controlflow_node {
5656 )
5757 }
5858
59+ /**
60+ * Gets the type of the `i`th operand. Unlike `getOperand(i).getType()`, this
61+ * predicate takes into account when there are multiple possible operands with
62+ * different types.
63+ */
64+ Type getOperandType ( int i ) {
65+ strictcount ( this .getOperand ( i ) ) = 1 and
66+ result = this .getOperand ( i ) .getType ( )
67+ or
68+ strictcount ( this .getOperand ( i ) ) = 2 and
69+ exists ( ControlFlowNode op1 , ControlFlowNode op2 , Type t2 |
70+ op1 = this .getOperand ( i ) and
71+ op2 = this .getOperand ( i ) and
72+ op1 != op2 and
73+ result = op1 .getType ( ) and
74+ t2 = op2 .getType ( )
75+ |
76+ result = t2
77+ or
78+ result .( PrimitiveType ) .getUnderlyingType ( ) .getConversionIndex ( ) >
79+ t2 .( PrimitiveType ) .getUnderlyingType ( ) .getConversionIndex ( )
80+ or
81+ op2 instanceof NullLiteral
82+ )
83+ }
84+
5985 /** Gets an operand of this instruction, if any. */
6086 ControlFlowNode getAnOperand ( ) { result = this .getOperand ( _) }
6187
@@ -102,7 +128,12 @@ class ControlFlowNode extends @cil_controlflow_node {
102128 /** Gets the method containing this control flow node. */
103129 MethodImplementation getImplementation ( ) { none ( ) }
104130
105- /** Gets the type of the item pushed onto the stack, if any. */
131+ /**
132+ * Gets the type of the item pushed onto the stack, if any.
133+ *
134+ * If called via `ControlFlowNode::getOperand(i).getType()`, consider using
135+ * `ControlFlowNode::getOperandType(i)` instead.
136+ */
106137 cached
107138 Type getType ( ) { none ( ) }
108139
0 commit comments