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 {
@@ -208,71 +209,7 @@ class CompileTimeConstantExpr extends Expr {
208209 // Literal value.
209210 result = this .( BooleanLiteral ) .getBooleanValue ( )
210211 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- )
212+ result = CalcCompileTimeConstants:: calculateBooleanValue ( this )
276213 or
277214 // Handle binary expressions that have `String` operands and a boolean result.
278215 exists ( BinaryExpr b , string left , string right |
@@ -300,18 +237,6 @@ class CompileTimeConstantExpr extends Expr {
300237 )
301238 or
302239 // 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
315240 result = this .( LiveLiteral ) .getValue ( ) .getBooleanValue ( )
316241 }
317242
@@ -329,75 +254,20 @@ class CompileTimeConstantExpr extends Expr {
329254 result = this .( IntegerLiteral ) .getIntValue ( )
330255 or
331256 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- )
395257 )
396258 or
259+ result = CalcCompileTimeConstants:: calculateIntValue ( this )
260+ or
397261 result = this .( LiveLiteral ) .getValue ( ) .getIntValue ( )
398262 }
399263}
400264
265+ private boolean getBoolValue ( Expr e ) { result = e .( CompileTimeConstantExpr ) .getBooleanValue ( ) }
266+
267+ private int getIntValue ( Expr e ) { result = e .( CompileTimeConstantExpr ) .getIntValue ( ) }
268+
269+ private module CalcCompileTimeConstants = CalculateConstants< getBoolValue / 1 , getIntValue / 1 > ;
270+
401271/** An expression parent is an element that may have an expression as its child. */
402272class ExprParent extends @exprparent, Top { }
403273
0 commit comments