@@ -279,20 +279,62 @@ private predicate reachableRecursive(ControlFlowNode n) {
279279 reachableRecursive ( n .getAPredecessor ( ) )
280280}
281281
282+ /** Holds if `e` is a compile time constant with integer value `val`. */
282283private predicate compileTimeConstantInt ( Expr e , int val ) {
283- val = e .getFullyConverted ( ) .getValue ( ) .toInt ( ) and
284- not e instanceof StringLiteral and
285- not exists ( Expr e1 | e1 .getConversion ( ) = e ) // only values for fully converted expressions
284+ (
285+ // If we have an integer value then we are done.
286+ if exists ( e .getValue ( ) .toInt ( ) )
287+ then val = e .getValue ( ) .toInt ( )
288+ else
289+ // Otherwise, if we are a conversion of another expression with an
290+ // integer value, and that value can be converted into our type,
291+ // then we have that value.
292+ exists ( Expr x , int valx |
293+ x .getConversion ( ) = e and
294+ compileTimeConstantInt ( x , valx ) and
295+ val = convertIntToType ( valx , e .getType ( ) .getUnspecifiedType ( ) )
296+ )
297+ ) and
298+ // If our unconverted expression is a string literal `"123"`, then we
299+ // do not have integer value `123`.
300+ not e .getUnconverted ( ) instanceof StringLiteral
286301}
287302
288- library class CompileTimeConstantInt extends Expr {
289- CompileTimeConstantInt ( ) { compileTimeConstantInt ( this , _) }
303+ /**
304+ * Get `val` represented as type `t`, if that is possible without
305+ * overflow or underflows.
306+ */
307+ bindingset [ val, t]
308+ private int convertIntToType ( int val , IntegralType t ) {
309+ if t instanceof BoolType
310+ then if val = 0 then result = 0 else result = 1
311+ else
312+ if t .isUnsigned ( )
313+ then if val >= 0 and val .bitShiftRight ( t .getSize ( ) * 8 ) = 0 then result = val else none ( )
314+ else
315+ if val >= 0 and val .bitShiftRight ( t .getSize ( ) * 8 - 1 ) = 0
316+ then result = val
317+ else
318+ if ( - ( val + 1 ) ) .bitShiftRight ( t .getSize ( ) * 8 - 1 ) = 0
319+ then result = val
320+ else none ( )
321+ }
322+
323+ /**
324+ * INTERNAL: Do not use.
325+ * An expression that has been found to have an integer value at compile
326+ * time.
327+ */
328+ class CompileTimeConstantInt extends Expr {
329+ int val ;
330+
331+ CompileTimeConstantInt ( ) { compileTimeConstantInt ( this .getFullyConverted ( ) , val ) }
290332
291- int getIntValue ( ) { compileTimeConstantInt ( this , result ) }
333+ int getIntValue ( ) { result = val }
292334}
293335
294336library class CompileTimeVariableExpr extends Expr {
295- CompileTimeVariableExpr ( ) { not compileTimeConstantInt ( this , _ ) }
337+ CompileTimeVariableExpr ( ) { not this instanceof CompileTimeConstantInt }
296338}
297339
298340/** A helper class for evaluation of expressions. */
0 commit comments