Skip to content

Commit bcf71d0

Browse files
authored
Merge pull request #22043 from github/copilot/tweak-ruby-ast-caseexpr
Ruby: synthesize implicit `true` value for valueless `CaseExpr`
2 parents 29eba2f + 5047bee commit bcf71d0

9 files changed

Lines changed: 233 additions & 206 deletions

File tree

ruby/ql/lib/codeql/ruby/ast/Control.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ class TernaryIfExpr extends ConditionalExpr, TTernaryIfExpr {
355355
*/
356356
class CaseExpr extends ControlExpr instanceof CaseExprImpl {
357357
/**
358-
* Gets the expression being compared, if any. For example, `foo` in the following example.
358+
* Gets the expression being compared. For example, `foo` in the following example.
359359
* ```rb
360360
* case foo
361361
* when 0
@@ -364,7 +364,7 @@ class CaseExpr extends ControlExpr instanceof CaseExprImpl {
364364
* puts 'one'
365365
* end
366366
* ```
367-
* There is no result for the following example:
367+
* In the following example, the result is an implicit synthesized `true` literal.
368368
* ```rb
369369
* case
370370
* when a then 0

ruby/ql/lib/codeql/ruby/ast/internal/Control.qll

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ class CaseWhenClause extends CaseExprImpl, TCaseExpr {
1616

1717
CaseWhenClause() { this = TCaseExpr(g) }
1818

19-
final override Expr getValue() { toGenerated(result) = g.getValue() }
19+
final override Expr getValue() {
20+
toGenerated(result) = g.getValue()
21+
or
22+
not exists(g.getValue()) and synthChild(this, -2, result)
23+
}
2024

2125
final override AstNode getBranch(int n) {
2226
// When branches map directly to WhenClause nodes

ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2002,6 +2002,25 @@ private module CallableBodySynthesis {
20022002
}
20032003
}
20042004

2005+
private module CaseNoValueSynthesis {
2006+
pragma[nomagic]
2007+
private predicate caseNoValueSynthesis(AstNode parent, int i, Child child) {
2008+
// Synthesize a `true` literal as the value of a `case`/`when` expression that has no value
2009+
exists(Ruby::Case g |
2010+
not exists(g.getValue()) and
2011+
parent = TCaseExpr(g) and
2012+
child = SynthChild(BooleanLiteralKind(true)) and
2013+
i = -2
2014+
)
2015+
}
2016+
2017+
private class CaseNoValueSynthesisImpl extends Synthesis {
2018+
final override predicate child(AstNode parent, int i, Child child) {
2019+
caseNoValueSynthesis(parent, i, child)
2020+
}
2021+
}
2022+
}
2023+
20052024
private module CaseElseBranchSynthesis {
20062025
pragma[nomagic]
20072026
private predicate caseElseBranchSynthesis(AstNode parent, int i, Child child) {

ruby/ql/test/library-tests/ast/Ast.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,7 @@ control/cases.rb:
829829
# 13| getBody: [StmtSequence] else ...
830830
# 14| getStmt: [IntegerLiteral] 300
831831
# 18| getStmt: [CaseExpr] case ...
832+
# 18| getValue: [BooleanLiteral] true
832833
# 19| getBranch: [WhenClause] when ...
833834
# 19| getPattern: [GTExpr] ... > ...
834835
# 19| getAnOperand/getGreaterOperand/getLeftOperand/getReceiver: [LocalVariableAccess] a

ruby/ql/test/library-tests/ast/ValueText.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ exprValue
131131
| control/cases.rb:11:9:11:9 | d | 0 | int |
132132
| control/cases.rb:12:5:12:7 | 200 | 200 | int |
133133
| control/cases.rb:14:5:14:7 | 300 | 300 | int |
134+
| control/cases.rb:18:1:22:3 | true | true | boolean |
134135
| control/cases.rb:19:6:19:6 | a | 0 | int |
135136
| control/cases.rb:19:10:19:10 | b | 0 | int |
136137
| control/cases.rb:19:18:19:19 | 10 | 10 | int |
@@ -1094,6 +1095,7 @@ exprCfgNodeValue
10941095
| control/cases.rb:11:9:11:9 | d | 0 | int |
10951096
| control/cases.rb:12:5:12:7 | 200 | 200 | int |
10961097
| control/cases.rb:14:5:14:7 | 300 | 300 | int |
1098+
| control/cases.rb:18:1:22:3 | true | true | boolean |
10971099
| control/cases.rb:19:6:19:6 | a | 0 | int |
10981100
| control/cases.rb:19:10:19:10 | b | 0 | int |
10991101
| control/cases.rb:19:18:19:19 | 10 | 10 | int |

ruby/ql/test/library-tests/ast/control/CaseExpr.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
caseValues
22
| cases.rb:8:1:15:3 | case ... | cases.rb:8:6:8:6 | a |
3+
| cases.rb:18:1:22:3 | case ... | cases.rb:18:1:22:3 | true |
34
| cases.rb:26:1:29:3 | case ... | cases.rb:26:6:26:9 | call to expr |
45
| cases.rb:31:1:37:3 | case ... | cases.rb:31:6:31:9 | call to expr |
56
| cases.rb:39:1:80:3 | case ... | cases.rb:39:6:39:9 | call to expr |
@@ -15,7 +16,6 @@ caseValues
1516
| cases.rb:164:1:167:3 | case ... | cases.rb:165:3:165:5 | foo |
1617
| cases.rb:169:1:172:3 | case ... | cases.rb:170:3:170:5 | foo |
1718
caseNoValues
18-
| cases.rb:18:1:22:3 | case ... |
1919
caseElseBranches
2020
| cases.rb:8:1:15:3 | case ... | cases.rb:13:1:14:7 | else ... |
2121
| cases.rb:26:1:29:3 | case ... | cases.rb:28:3:28:12 | else ... |

ruby/ql/test/library-tests/controlflow/graph/BasicBlocks.expected

Lines changed: 151 additions & 151 deletions
Large diffs are not rendered by default.

ruby/ql/test/library-tests/controlflow/graph/Cfg.expected

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@
649649
| cfg.rb:39:1:39:4 | self | cfg.rb:39:11:39:12 | 42 | |
650650
| cfg.rb:39:1:39:12 | call to puts | cfg.rb:41:6:41:7 | 10 | |
651651
| cfg.rb:39:11:39:12 | 42 | cfg.rb:39:1:39:12 | call to puts | |
652-
| cfg.rb:41:1:45:3 | case ... | cfg.rb:48:8:48:8 | b | |
652+
| cfg.rb:41:1:45:3 | case ... | cfg.rb:47:1:50:3 | true | |
653653
| cfg.rb:41:6:41:7 | 10 | cfg.rb:42:8:42:8 | 1 | |
654654
| cfg.rb:42:3:42:24 | [match] when ... | cfg.rb:42:15:42:24 | self | match |
655655
| cfg.rb:42:3:42:24 | [no-match] when ... | cfg.rb:43:8:43:8 | 2 | no-match |
@@ -679,26 +679,27 @@
679679
| cfg.rb:44:13:44:18 | "many" | cfg.rb:44:8:44:18 | call to puts | |
680680
| cfg.rb:44:14:44:17 | many | cfg.rb:44:13:44:18 | "many" | |
681681
| cfg.rb:47:1:50:3 | case ... | cfg.rb:52:1:52:7 | chained | |
682-
| cfg.rb:48:3:48:29 | [false] when ... | cfg.rb:49:8:49:8 | b | false |
683-
| cfg.rb:48:3:48:29 | [true] when ... | cfg.rb:48:20:48:29 | self | true |
682+
| cfg.rb:47:1:50:3 | true | cfg.rb:48:8:48:8 | b | |
683+
| cfg.rb:48:3:48:29 | [match] when ... | cfg.rb:48:20:48:29 | self | match |
684+
| cfg.rb:48:3:48:29 | [no-match] when ... | cfg.rb:49:8:49:8 | b | no-match |
684685
| cfg.rb:48:8:48:8 | b | cfg.rb:48:13:48:13 | 1 | |
685-
| cfg.rb:48:8:48:13 | ... == ... | cfg.rb:48:3:48:29 | [false] when ... | false |
686-
| cfg.rb:48:8:48:13 | ... == ... | cfg.rb:48:3:48:29 | [true] when ... | true |
686+
| cfg.rb:48:8:48:13 | ... == ... | cfg.rb:48:3:48:29 | [match] when ... | match |
687+
| cfg.rb:48:8:48:13 | ... == ... | cfg.rb:48:3:48:29 | [no-match] when ... | no-match |
687688
| cfg.rb:48:13:48:13 | 1 | cfg.rb:48:8:48:13 | ... == ... | |
688689
| cfg.rb:48:15:48:29 | then ... | cfg.rb:47:1:50:3 | case ... | |
689690
| cfg.rb:48:20:48:29 | call to puts | cfg.rb:48:15:48:29 | then ... | |
690691
| cfg.rb:48:20:48:29 | self | cfg.rb:48:26:48:28 | one | |
691692
| cfg.rb:48:25:48:29 | "one" | cfg.rb:48:20:48:29 | call to puts | |
692693
| cfg.rb:48:26:48:28 | one | cfg.rb:48:25:48:29 | "one" | |
693-
| cfg.rb:49:3:49:37 | [false] when ... | cfg.rb:47:1:50:3 | case ... | false |
694-
| cfg.rb:49:3:49:37 | [true] when ... | cfg.rb:49:27:49:37 | self | true |
694+
| cfg.rb:49:3:49:37 | [match] when ... | cfg.rb:49:27:49:37 | self | match |
695+
| cfg.rb:49:3:49:37 | [no-match] when ... | cfg.rb:47:1:50:3 | case ... | no-match |
695696
| cfg.rb:49:8:49:8 | b | cfg.rb:49:13:49:13 | 0 | |
696-
| cfg.rb:49:8:49:13 | ... == ... | cfg.rb:49:3:49:37 | [true] when ... | true |
697-
| cfg.rb:49:8:49:13 | ... == ... | cfg.rb:49:16:49:16 | b | false |
697+
| cfg.rb:49:8:49:13 | ... == ... | cfg.rb:49:3:49:37 | [match] when ... | match |
698+
| cfg.rb:49:8:49:13 | ... == ... | cfg.rb:49:16:49:16 | b | no-match |
698699
| cfg.rb:49:13:49:13 | 0 | cfg.rb:49:8:49:13 | ... == ... | |
699700
| cfg.rb:49:16:49:16 | b | cfg.rb:49:20:49:20 | 1 | |
700-
| cfg.rb:49:16:49:20 | ... > ... | cfg.rb:49:3:49:37 | [false] when ... | false |
701-
| cfg.rb:49:16:49:20 | ... > ... | cfg.rb:49:3:49:37 | [true] when ... | true |
701+
| cfg.rb:49:16:49:20 | ... > ... | cfg.rb:49:3:49:37 | [match] when ... | match |
702+
| cfg.rb:49:16:49:20 | ... > ... | cfg.rb:49:3:49:37 | [no-match] when ... | no-match |
702703
| cfg.rb:49:20:49:20 | 1 | cfg.rb:49:16:49:20 | ... > ... | |
703704
| cfg.rb:49:22:49:37 | then ... | cfg.rb:47:1:50:3 | case ... | |
704705
| cfg.rb:49:27:49:37 | call to puts | cfg.rb:49:22:49:37 | then ... | |

ruby/ql/test/library-tests/dataflow/barrier-guards/barrier-guards.expected

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -266,46 +266,46 @@ controls
266266
| barrier-guards.rb:227:4:227:21 | [true] ... and ... | barrier-guards.rb:228:5:228:7 | self | true |
267267
| barrier-guards.rb:227:21:227:21 | call to y | barrier-guards.rb:227:4:227:21 | [true] ... and ... | true |
268268
| barrier-guards.rb:227:21:227:21 | call to y | barrier-guards.rb:228:5:228:7 | self | true |
269-
| barrier-guards.rb:232:1:233:19 | [true] when ... | barrier-guards.rb:233:5:233:7 | foo | true |
270-
| barrier-guards.rb:232:6:232:17 | ... == ... | barrier-guards.rb:232:1:233:19 | [false] when ... | false |
271-
| barrier-guards.rb:232:6:232:17 | ... == ... | barrier-guards.rb:232:1:233:19 | [true] when ... | true |
272-
| barrier-guards.rb:232:6:232:17 | ... == ... | barrier-guards.rb:233:5:233:7 | foo | true |
273-
| barrier-guards.rb:237:1:237:38 | [false] when ... | barrier-guards.rb:238:1:238:26 | [false] when ... | false |
274-
| barrier-guards.rb:237:1:237:38 | [false] when ... | barrier-guards.rb:238:1:238:26 | [true] when ... | false |
275-
| barrier-guards.rb:237:1:237:38 | [false] when ... | barrier-guards.rb:238:6:238:8 | self | false |
276-
| barrier-guards.rb:237:1:237:38 | [false] when ... | barrier-guards.rb:238:24:238:26 | foo | false |
277-
| barrier-guards.rb:237:1:237:38 | [false] when ... | barrier-guards.rb:239:1:239:22 | [false] when ... | false |
278-
| barrier-guards.rb:237:1:237:38 | [false] when ... | barrier-guards.rb:239:1:239:22 | [true] when ... | false |
279-
| barrier-guards.rb:237:1:237:38 | [false] when ... | barrier-guards.rb:239:6:239:8 | foo | false |
280-
| barrier-guards.rb:237:1:237:38 | [false] when ... | barrier-guards.rb:239:20:239:22 | foo | false |
281-
| barrier-guards.rb:237:1:237:38 | [true] when ... | barrier-guards.rb:237:24:237:26 | foo | true |
282-
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:237:1:237:38 | [false] when ... | false |
283-
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:237:1:237:38 | [true] when ... | true |
284-
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:237:24:237:26 | foo | true |
285-
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:238:1:238:26 | [false] when ... | false |
286-
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:238:1:238:26 | [true] when ... | false |
287-
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:238:6:238:8 | self | false |
288-
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:238:24:238:26 | foo | false |
289-
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:239:1:239:22 | [false] when ... | false |
290-
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:239:1:239:22 | [true] when ... | false |
291-
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:239:6:239:8 | foo | false |
292-
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:239:20:239:22 | foo | false |
293-
| barrier-guards.rb:238:1:238:26 | [false] when ... | barrier-guards.rb:239:1:239:22 | [false] when ... | false |
294-
| barrier-guards.rb:238:1:238:26 | [false] when ... | barrier-guards.rb:239:1:239:22 | [true] when ... | false |
295-
| barrier-guards.rb:238:1:238:26 | [false] when ... | barrier-guards.rb:239:6:239:8 | foo | false |
296-
| barrier-guards.rb:238:1:238:26 | [false] when ... | barrier-guards.rb:239:20:239:22 | foo | false |
297-
| barrier-guards.rb:238:1:238:26 | [true] when ... | barrier-guards.rb:238:24:238:26 | foo | true |
298-
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:238:1:238:26 | [false] when ... | false |
299-
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:238:1:238:26 | [true] when ... | true |
300-
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:238:24:238:26 | foo | true |
301-
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:239:1:239:22 | [false] when ... | false |
302-
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:239:1:239:22 | [true] when ... | false |
303-
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:239:6:239:8 | foo | false |
304-
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:239:20:239:22 | foo | false |
305-
| barrier-guards.rb:239:1:239:22 | [true] when ... | barrier-guards.rb:239:20:239:22 | foo | true |
306-
| barrier-guards.rb:239:6:239:13 | ... == ... | barrier-guards.rb:239:1:239:22 | [false] when ... | false |
307-
| barrier-guards.rb:239:6:239:13 | ... == ... | barrier-guards.rb:239:1:239:22 | [true] when ... | true |
308-
| barrier-guards.rb:239:6:239:13 | ... == ... | barrier-guards.rb:239:20:239:22 | foo | true |
269+
| barrier-guards.rb:232:1:233:19 | [match] when ... | barrier-guards.rb:233:5:233:7 | foo | match |
270+
| barrier-guards.rb:232:6:232:17 | ... == ... | barrier-guards.rb:232:1:233:19 | [match] when ... | match |
271+
| barrier-guards.rb:232:6:232:17 | ... == ... | barrier-guards.rb:232:1:233:19 | [no-match] when ... | no-match |
272+
| barrier-guards.rb:232:6:232:17 | ... == ... | barrier-guards.rb:233:5:233:7 | foo | match |
273+
| barrier-guards.rb:237:1:237:38 | [match] when ... | barrier-guards.rb:237:24:237:26 | foo | match |
274+
| barrier-guards.rb:237:1:237:38 | [no-match] when ... | barrier-guards.rb:238:1:238:26 | [match] when ... | no-match |
275+
| barrier-guards.rb:237:1:237:38 | [no-match] when ... | barrier-guards.rb:238:1:238:26 | [no-match] when ... | no-match |
276+
| barrier-guards.rb:237:1:237:38 | [no-match] when ... | barrier-guards.rb:238:6:238:8 | self | no-match |
277+
| barrier-guards.rb:237:1:237:38 | [no-match] when ... | barrier-guards.rb:238:24:238:26 | foo | no-match |
278+
| barrier-guards.rb:237:1:237:38 | [no-match] when ... | barrier-guards.rb:239:1:239:22 | [match] when ... | no-match |
279+
| barrier-guards.rb:237:1:237:38 | [no-match] when ... | barrier-guards.rb:239:1:239:22 | [no-match] when ... | no-match |
280+
| barrier-guards.rb:237:1:237:38 | [no-match] when ... | barrier-guards.rb:239:6:239:8 | foo | no-match |
281+
| barrier-guards.rb:237:1:237:38 | [no-match] when ... | barrier-guards.rb:239:20:239:22 | foo | no-match |
282+
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:237:1:237:38 | [match] when ... | match |
283+
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:237:1:237:38 | [no-match] when ... | no-match |
284+
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:237:24:237:26 | foo | match |
285+
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:238:1:238:26 | [match] when ... | no-match |
286+
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:238:1:238:26 | [no-match] when ... | no-match |
287+
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:238:6:238:8 | self | no-match |
288+
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:238:24:238:26 | foo | no-match |
289+
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:239:1:239:22 | [match] when ... | no-match |
290+
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:239:1:239:22 | [no-match] when ... | no-match |
291+
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:239:6:239:8 | foo | no-match |
292+
| barrier-guards.rb:237:6:237:17 | ... == ... | barrier-guards.rb:239:20:239:22 | foo | no-match |
293+
| barrier-guards.rb:238:1:238:26 | [match] when ... | barrier-guards.rb:238:24:238:26 | foo | match |
294+
| barrier-guards.rb:238:1:238:26 | [no-match] when ... | barrier-guards.rb:239:1:239:22 | [match] when ... | no-match |
295+
| barrier-guards.rb:238:1:238:26 | [no-match] when ... | barrier-guards.rb:239:1:239:22 | [no-match] when ... | no-match |
296+
| barrier-guards.rb:238:1:238:26 | [no-match] when ... | barrier-guards.rb:239:6:239:8 | foo | no-match |
297+
| barrier-guards.rb:238:1:238:26 | [no-match] when ... | barrier-guards.rb:239:20:239:22 | foo | no-match |
298+
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:238:1:238:26 | [match] when ... | match |
299+
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:238:1:238:26 | [no-match] when ... | no-match |
300+
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:238:24:238:26 | foo | match |
301+
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:239:1:239:22 | [match] when ... | no-match |
302+
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:239:1:239:22 | [no-match] when ... | no-match |
303+
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:239:6:239:8 | foo | no-match |
304+
| barrier-guards.rb:238:6:238:17 | ... == ... | barrier-guards.rb:239:20:239:22 | foo | no-match |
305+
| barrier-guards.rb:239:1:239:22 | [match] when ... | barrier-guards.rb:239:20:239:22 | foo | match |
306+
| barrier-guards.rb:239:6:239:13 | ... == ... | barrier-guards.rb:239:1:239:22 | [match] when ... | match |
307+
| barrier-guards.rb:239:6:239:13 | ... == ... | barrier-guards.rb:239:1:239:22 | [no-match] when ... | no-match |
308+
| barrier-guards.rb:239:6:239:13 | ... == ... | barrier-guards.rb:239:20:239:22 | foo | match |
309309
| barrier-guards.rb:243:4:243:8 | "foo" | barrier-guards.rb:244:5:244:7 | foo | match |
310310
| barrier-guards.rb:243:4:243:8 | "foo" | barrier-guards.rb:245:1:246:7 | in ... then ... | no-match |
311311
| barrier-guards.rb:243:4:243:8 | "foo" | barrier-guards.rb:246:5:246:7 | foo | no-match |

0 commit comments

Comments
 (0)