@@ -156,8 +156,65 @@ float safeFloor(float v) {
156156 result = v
157157}
158158
159+ /** A `MulExpr` where exactly one operand is constant. */
160+ private class MulByConstantExpr extends MulExpr {
161+ float constant ;
162+ Expr operand ;
163+
164+ MulByConstantExpr ( ) {
165+ exists ( Expr constantExpr |
166+ this .hasOperands ( constantExpr , operand ) and
167+ constant = constantExpr .getFullyConverted ( ) .getValue ( ) .toFloat ( ) and
168+ not exists ( operand .getFullyConverted ( ) .getValue ( ) .toFloat ( ) )
169+ )
170+ }
171+
172+ /** Gets the value of the constant operand. */
173+ float getConstant ( ) { result = constant }
174+
175+ /** Gets the non-constant operand. */
176+ Expr getOperand ( ) { result = operand }
177+ }
178+
159179private class UnsignedMulExpr extends MulExpr {
160- UnsignedMulExpr ( ) { this .getType ( ) .( IntegralType ) .isUnsigned ( ) }
180+ UnsignedMulExpr ( ) {
181+ this .getType ( ) .( IntegralType ) .isUnsigned ( ) and
182+ // Avoid overlap. It should be slightly cheaper to analyze
183+ // `MulByConstantExpr`.
184+ not this instanceof MulByConstantExpr
185+ }
186+ }
187+
188+ /**
189+ * Holds if `expr` is effectively a multiplication of `operand` with the
190+ * positive constant `positive`.
191+ */
192+ private predicate multipliesByPositive ( Expr expr , Expr operand , float positive ) {
193+ operand = expr .( MulByConstantExpr ) .getOperand ( ) and
194+ positive = expr .( MulByConstantExpr ) .getConstant ( ) and
195+ positive >= 0.0 // includes positive zero
196+ or
197+ operand = expr .( UnaryPlusExpr ) .getOperand ( ) and
198+ positive = 1.0
199+ or
200+ operand = expr .( CommaExpr ) .getRightOperand ( ) and
201+ positive = 1.0
202+ or
203+ operand = expr .( StmtExpr ) .getResultExpr ( ) and
204+ positive = 1.0
205+ }
206+
207+ /**
208+ * Holds if `expr` is effectively a multiplication of `operand` with the
209+ * negative constant `negative`.
210+ */
211+ private predicate multipliesByNegative ( Expr expr , Expr operand , float negative ) {
212+ operand = expr .( MulByConstantExpr ) .getOperand ( ) and
213+ negative = expr .( MulByConstantExpr ) .getConstant ( ) and
214+ negative < 0.0 // includes negative zero
215+ or
216+ operand = expr .( UnaryMinusExpr ) .getOperand ( ) and
217+ negative = - 1.0
161218}
162219
163220private class UnsignedAssignMulExpr extends AssignMulExpr {
@@ -172,9 +229,9 @@ private predicate analyzableExpr(Expr e) {
172229 (
173230 exists ( getValue ( e ) .toFloat ( ) )
174231 or
175- e instanceof UnaryPlusExpr
232+ multipliesByPositive ( e , _ , _ )
176233 or
177- e instanceof UnaryMinusExpr
234+ multipliesByNegative ( e , _ , _ )
178235 or
179236 e instanceof MinExpr
180237 or
@@ -200,10 +257,6 @@ private predicate analyzableExpr(Expr e) {
200257 or
201258 e instanceof RemExpr
202259 or
203- e instanceof CommaExpr
204- or
205- e instanceof StmtExpr
206- or
207260 // A conversion is analyzable, provided that its child has an arithmetic
208261 // type. (Sometimes the child is a reference type, and so does not get
209262 // any bounds.) Rather than checking whether the type of the child is
@@ -272,12 +325,14 @@ private predicate defDependsOnDef(
272325 * the structure of `getLowerBoundsImpl` and `getUpperBoundsImpl`.
273326 */
274327private predicate exprDependsOnDef ( Expr e , RangeSsaDefinition srcDef , StackVariable srcVar ) {
275- exists ( UnaryMinusExpr negateExpr | e = negateExpr |
276- exprDependsOnDef ( negateExpr .getOperand ( ) , srcDef , srcVar )
328+ exists ( Expr operand |
329+ multipliesByNegative ( e , operand , _) and
330+ exprDependsOnDef ( operand , srcDef , srcVar )
277331 )
278332 or
279- exists ( UnaryPlusExpr plusExpr | e = plusExpr |
280- exprDependsOnDef ( plusExpr .getOperand ( ) , srcDef , srcVar )
333+ exists ( Expr operand |
334+ multipliesByPositive ( e , operand , _) and
335+ exprDependsOnDef ( operand , srcDef , srcVar )
281336 )
282337 or
283338 exists ( MinExpr minExpr | e = minExpr | exprDependsOnDef ( minExpr .getAnOperand ( ) , srcDef , srcVar ) )
@@ -316,14 +371,6 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria
316371 or
317372 exists ( RemExpr remExpr | e = remExpr | exprDependsOnDef ( remExpr .getAnOperand ( ) , srcDef , srcVar ) )
318373 or
319- exists ( CommaExpr commaExpr | e = commaExpr |
320- exprDependsOnDef ( commaExpr .getRightOperand ( ) , srcDef , srcVar )
321- )
322- or
323- exists ( StmtExpr stmtExpr | e = stmtExpr |
324- exprDependsOnDef ( stmtExpr .getResultExpr ( ) , srcDef , srcVar )
325- )
326- or
327374 exists ( Conversion convExpr | e = convExpr | exprDependsOnDef ( convExpr .getExpr ( ) , srcDef , srcVar ) )
328375 or
329376 // unsigned `&`
@@ -592,15 +639,16 @@ deprecated predicate positive_overflow(Expr expr) { exprMightOverflowPositively(
592639
593640/** Only to be called by `getTruncatedLowerBounds`. */
594641private float getLowerBoundsImpl ( Expr expr ) {
595- exists ( UnaryPlusExpr plusExpr |
596- expr = plusExpr and
597- result = getFullyConvertedLowerBounds ( plusExpr .getOperand ( ) )
642+ exists ( Expr operand , float operandLow , float positive |
643+ multipliesByPositive ( expr , operand , positive ) and
644+ operandLow = getFullyConvertedLowerBounds ( operand ) and
645+ result = positive * operandLow
598646 )
599647 or
600- exists ( UnaryMinusExpr negateExpr , float xHigh |
601- expr = negateExpr and
602- xHigh = getFullyConvertedUpperBounds ( negateExpr . getOperand ( ) ) and
603- result = - xHigh
648+ exists ( Expr operand , float operandHigh , float negative |
649+ multipliesByNegative ( expr , operand , negative ) and
650+ operandHigh = getFullyConvertedUpperBounds ( operand ) and
651+ result = negative * operandHigh
604652 )
605653 or
606654 exists ( MinExpr minExpr |
@@ -732,16 +780,6 @@ private float getLowerBoundsImpl(Expr expr) {
732780 )
733781 )
734782 or
735- exists ( CommaExpr commaExpr |
736- expr = commaExpr and
737- result = getFullyConvertedLowerBounds ( commaExpr .getRightOperand ( ) )
738- )
739- or
740- exists ( StmtExpr stmtExpr |
741- expr = stmtExpr and
742- result = getFullyConvertedLowerBounds ( stmtExpr .getResultExpr ( ) )
743- )
744- or
745783 // If the conversion is to an arithmetic type then we just return the
746784 // lower bound of the child. We do not need to handle truncation and
747785 // overflow here, because that is done in `getTruncatedLowerBounds`.
@@ -775,15 +813,16 @@ private float getLowerBoundsImpl(Expr expr) {
775813
776814/** Only to be called by `getTruncatedUpperBounds`. */
777815private float getUpperBoundsImpl ( Expr expr ) {
778- exists ( UnaryPlusExpr plusExpr |
779- expr = plusExpr and
780- result = getFullyConvertedUpperBounds ( plusExpr .getOperand ( ) )
816+ exists ( Expr operand , float operandHigh , float positive |
817+ multipliesByPositive ( expr , operand , positive ) and
818+ operandHigh = getFullyConvertedUpperBounds ( operand ) and
819+ result = positive * operandHigh
781820 )
782821 or
783- exists ( UnaryMinusExpr negateExpr , float xLow |
784- expr = negateExpr and
785- xLow = getFullyConvertedLowerBounds ( negateExpr . getOperand ( ) ) and
786- result = - xLow
822+ exists ( Expr operand , float operandLow , float negative |
823+ multipliesByNegative ( expr , operand , negative ) and
824+ operandLow = getFullyConvertedLowerBounds ( operand ) and
825+ result = negative * operandLow
787826 )
788827 or
789828 exists ( MaxExpr maxExpr |
@@ -913,16 +952,6 @@ private float getUpperBoundsImpl(Expr expr) {
913952 )
914953 )
915954 or
916- exists ( CommaExpr commaExpr |
917- expr = commaExpr and
918- result = getFullyConvertedUpperBounds ( commaExpr .getRightOperand ( ) )
919- )
920- or
921- exists ( StmtExpr stmtExpr |
922- expr = stmtExpr and
923- result = getFullyConvertedUpperBounds ( stmtExpr .getResultExpr ( ) )
924- )
925- or
926955 // If the conversion is to an arithmetic type then we just return the
927956 // upper bound of the child. We do not need to handle truncation and
928957 // overflow here, because that is done in `getTruncatedUpperBounds`.
0 commit comments