44
55import java
66private import semmle.code.java.frameworks.android.Compose
7+ private import semmle.code.java.Constants
78
89/** A common super-class that represents all kinds of expressions. */
910class Expr extends ExprParent , @expr {
@@ -130,6 +131,7 @@ private predicate primitiveOrString(Type t) {
130131 * See JLS v8, section 15.28 (Constant Expressions).
131132 */
132133class CompileTimeConstantExpr extends Expr {
134+ pragma [ assume_small_delta]
133135 CompileTimeConstantExpr ( ) {
134136 primitiveOrString ( this .getType ( ) ) and
135137 (
@@ -179,6 +181,7 @@ class CompileTimeConstantExpr extends Expr {
179181 /**
180182 * Gets the string value of this expression, where possible.
181183 */
184+ pragma [ assume_small_delta]
182185 pragma [ nomagic]
183186 string getStringValue ( ) {
184187 result = this .( StringLiteral ) .getValue ( )
@@ -204,75 +207,13 @@ class CompileTimeConstantExpr extends Expr {
204207 /**
205208 * Gets the boolean value of this expression, where possible.
206209 */
210+ pragma [ assume_small_delta]
211+ pragma [ nomagic]
207212 boolean getBooleanValue ( ) {
208213 // Literal value.
209214 result = this .( BooleanLiteral ) .getBooleanValue ( )
210215 or
211- // No casts relevant to booleans.
212- // `!` is the only unary operator that evaluates to a boolean.
213- result = this .( LogNotExpr ) .getExpr ( ) .( CompileTimeConstantExpr ) .getBooleanValue ( ) .booleanNot ( )
214- or
215- // Handle binary expressions that have integer operands and a boolean result.
216- exists ( BinaryExpr b , int left , int right |
217- b = this and
218- left = b .getLeftOperand ( ) .( CompileTimeConstantExpr ) .getIntValue ( ) and
219- right = b .getRightOperand ( ) .( CompileTimeConstantExpr ) .getIntValue ( )
220- |
221- (
222- b instanceof LTExpr and
223- if left < right then result = true else result = false
224- )
225- or
226- (
227- b instanceof LEExpr and
228- if left <= right then result = true else result = false
229- )
230- or
231- (
232- b instanceof GTExpr and
233- if left > right then result = true else result = false
234- )
235- or
236- (
237- b instanceof GEExpr and
238- if left >= right then result = true else result = false
239- )
240- or
241- (
242- b instanceof ValueOrReferenceEqualsExpr and
243- if left = right then result = true else result = false
244- )
245- or
246- (
247- b instanceof ValueOrReferenceNotEqualsExpr and
248- if left != right then result = true else result = false
249- )
250- )
251- or
252- // Handle binary expressions that have boolean operands and a boolean result.
253- exists ( BinaryExpr b , boolean left , boolean right |
254- b = this and
255- left = b .getLeftOperand ( ) .( CompileTimeConstantExpr ) .getBooleanValue ( ) and
256- right = b .getRightOperand ( ) .( CompileTimeConstantExpr ) .getBooleanValue ( )
257- |
258- (
259- b instanceof ValueOrReferenceEqualsExpr and
260- if left = right then result = true else result = false
261- )
262- or
263- (
264- b instanceof ValueOrReferenceNotEqualsExpr and
265- if left != right then result = true else result = false
266- )
267- or
268- ( b instanceof AndBitwiseExpr or b instanceof AndLogicalExpr ) and
269- result = left .booleanAnd ( right )
270- or
271- ( b instanceof OrBitwiseExpr or b instanceof OrLogicalExpr ) and
272- result = left .booleanOr ( right )
273- or
274- b instanceof XorBitwiseExpr and result = left .booleanXor ( right )
275- )
216+ result = CalcCompileTimeConstants:: calculateBooleanValue ( this )
276217 or
277218 // Handle binary expressions that have `String` operands and a boolean result.
278219 exists ( BinaryExpr b , string left , string right |
@@ -300,18 +241,6 @@ class CompileTimeConstantExpr extends Expr {
300241 )
301242 or
302243 // Note: no `getFloatValue()`, so we cannot support binary expressions with float or double operands.
303- // Ternary expressions, where the `true` and `false` expressions are boolean compile-time constants.
304- exists ( ConditionalExpr ce , boolean condition |
305- ce = this and
306- condition = ce .getCondition ( ) .( CompileTimeConstantExpr ) .getBooleanValue ( ) and
307- result = ce .getBranchExpr ( condition ) .( CompileTimeConstantExpr ) .getBooleanValue ( )
308- )
309- or
310- // Simple or qualified names where the variable is final and the initializer is a constant.
311- exists ( Variable v | this = v .getAnAccess ( ) |
312- result = v .getInitializer ( ) .( CompileTimeConstantExpr ) .getBooleanValue ( )
313- )
314- or
315244 result = this .( LiveLiteral ) .getValue ( ) .getBooleanValue ( )
316245 }
317246
@@ -329,75 +258,20 @@ class CompileTimeConstantExpr extends Expr {
329258 result = this .( IntegerLiteral ) .getIntValue ( )
330259 or
331260 result = this .( CharacterLiteral ) .getCodePointValue ( )
332- or
333- exists ( CastingExpr cast , int val |
334- cast = this and val = cast .getExpr ( ) .( CompileTimeConstantExpr ) .getIntValue ( )
335- |
336- if cast .getType ( ) .hasName ( "byte" )
337- then result = ( val + 128 ) .bitAnd ( 255 ) - 128
338- else
339- if cast .getType ( ) .hasName ( "short" )
340- then result = ( val + 32768 ) .bitAnd ( 65535 ) - 32768
341- else
342- if cast .getType ( ) .hasName ( "char" )
343- then result = val .bitAnd ( 65535 )
344- else result = val
345- )
346- or
347- result = this .( PlusExpr ) .getExpr ( ) .( CompileTimeConstantExpr ) .getIntValue ( )
348- or
349- result = - this .( MinusExpr ) .getExpr ( ) .( CompileTimeConstantExpr ) .getIntValue ( )
350- or
351- result = this .( BitNotExpr ) .getExpr ( ) .( CompileTimeConstantExpr ) .getIntValue ( ) .bitNot ( )
352- or
353- // No `int` value for `LogNotExpr`.
354- exists ( BinaryExpr b , int v1 , int v2 |
355- b = this and
356- v1 = b .getLeftOperand ( ) .( CompileTimeConstantExpr ) .getIntValue ( ) and
357- v2 = b .getRightOperand ( ) .( CompileTimeConstantExpr ) .getIntValue ( )
358- |
359- b instanceof MulExpr and result = v1 * v2
360- or
361- b instanceof DivExpr and result = v1 / v2
362- or
363- b instanceof RemExpr and result = v1 % v2
364- or
365- b instanceof AddExpr and result = v1 + v2
366- or
367- b instanceof SubExpr and result = v1 - v2
368- or
369- b instanceof LeftShiftExpr and result = v1 .bitShiftLeft ( v2 )
370- or
371- b instanceof RightShiftExpr and result = v1 .bitShiftRightSigned ( v2 )
372- or
373- b instanceof UnsignedRightShiftExpr and result = v1 .bitShiftRight ( v2 )
374- or
375- b instanceof AndBitwiseExpr and result = v1 .bitAnd ( v2 )
376- or
377- b instanceof OrBitwiseExpr and result = v1 .bitOr ( v2 )
378- or
379- b instanceof XorBitwiseExpr and result = v1 .bitXor ( v2 )
380- // No `int` value for `AndLogicalExpr` or `OrLogicalExpr`.
381- // No `int` value for `LTExpr`, `GTExpr`, `LEExpr`, `GEExpr`, `ValueOrReferenceEqualsExpr` or `ValueOrReferenceNotEqualsExpr`.
382- )
383- or
384- // Ternary conditional, with compile-time constant condition.
385- exists ( ConditionalExpr ce , boolean condition |
386- ce = this and
387- condition = ce .getCondition ( ) .( CompileTimeConstantExpr ) .getBooleanValue ( ) and
388- result = ce .getBranchExpr ( condition ) .( CompileTimeConstantExpr ) .getIntValue ( )
389- )
390- or
391- // If a `Variable` is a `CompileTimeConstantExpr`, its value is its initializer.
392- exists ( Variable v | this = v .getAnAccess ( ) |
393- result = v .getInitializer ( ) .( CompileTimeConstantExpr ) .getIntValue ( )
394- )
395261 )
396262 or
263+ result = CalcCompileTimeConstants:: calculateIntValue ( this )
264+ or
397265 result = this .( LiveLiteral ) .getValue ( ) .getIntValue ( )
398266 }
399267}
400268
269+ private boolean getBoolValue ( Expr e ) { result = e .( CompileTimeConstantExpr ) .getBooleanValue ( ) }
270+
271+ private int getIntValue ( Expr e ) { result = e .( CompileTimeConstantExpr ) .getIntValue ( ) }
272+
273+ private module CalcCompileTimeConstants = CalculateConstants< getBoolValue / 1 , getIntValue / 1 > ;
274+
401275/** An expression parent is an element that may have an expression as its child. */
402276class ExprParent extends @exprparent, Top { }
403277
0 commit comments