@@ -2133,3 +2133,41 @@ class Argument extends Expr {
21332133 )
21342134 }
21352135}
2136+
2137+ /**
2138+ * A statement expression, as specified by JLS 17 section 14.8.
2139+ * The result of a statement expression, if any, is discarded.
2140+ *
2141+ * Not to be confused with `ExprStmt`; while the child of an `ExprStmt` is always
2142+ * a `StmtExpr`, the opposite is not true. A `StmtExpr` occurs for example also
2143+ * as 'init' of a `for` statement.
2144+ */
2145+ class StmtExpr extends Expr {
2146+ StmtExpr ( ) {
2147+ this = any ( ExprStmt s ) .getExpr ( )
2148+ or
2149+ this = any ( ForStmt s ) .getAnInit ( ) and not this instanceof LocalVariableDeclExpr
2150+ or
2151+ this = any ( ForStmt s ) .getAnUpdate ( )
2152+ or
2153+ // Only applies to SwitchStmt, but not to SwitchExpr, see JLS 17 section 14.11.2
2154+ // TODO: Possibly redundant depending on how https://github.com/github/codeql/issues/8570 is resolved
2155+ this = any ( SwitchStmt s ) .getACase ( ) .getRuleExpression ( )
2156+ or
2157+ // TODO: Workarounds for https://github.com/github/codeql/issues/3605
2158+ exists ( LambdaExpr lambda |
2159+ this = lambda .getExprBody ( ) and
2160+ lambda .asMethod ( ) .getReturnType ( ) instanceof VoidType
2161+ )
2162+ or
2163+ exists ( MemberRefExpr memberRef , Method implicitMethod , Method overridden |
2164+ implicitMethod = memberRef .asMethod ( )
2165+ |
2166+ this .getParent ( ) .( ReturnStmt ) .getEnclosingCallable ( ) = implicitMethod and
2167+ // asMethod() has bogus method with wrong return type as result, e.g. `run(): String` (overriding `Runnable.run(): void`)
2168+ // Therefore need to check the overridden method
2169+ implicitMethod .getSourceDeclaration ( ) .overridesOrInstantiates * ( overridden ) and
2170+ overridden .getReturnType ( ) instanceof VoidType
2171+ )
2172+ }
2173+ }
0 commit comments