@@ -164,6 +164,39 @@ class Guard extends ExprParent {
164164 )
165165 }
166166
167+ /**
168+ * Holds if this guard tests whether `testedExpr` has type `testedType`.
169+ *
170+ * `restricted` is true if the test applies additional restrictions on top of just `testedType`, and so
171+ * this guard failing does not guarantee `testedExpr` is *not* a `testedType`-- for example,
172+ * matching `record R(Object o)` with `case R(String s)` is a guard with an additional restriction on the
173+ * type of field `o`, so the guard passing guarantees `testedExpr` is an `R`, but it failing does not
174+ * guarantee `testedExpr` is not an `R`.
175+ */
176+ predicate appliesTypeTest ( Expr testedExpr , Type testedType , boolean restricted ) {
177+ (
178+ exists ( InstanceOfExpr ioe | this = ioe |
179+ testedExpr = ioe .getExpr ( ) and
180+ testedType = ioe .getSyntacticCheckedType ( )
181+ )
182+ or
183+ exists ( PatternCase pc | this = pc |
184+ pc .getSelectorExpr ( ) = testedExpr and
185+ testedType = pc .getPattern ( ) .getType ( )
186+ )
187+ ) and
188+ (
189+ if
190+ exists ( RecordPatternExpr rpe |
191+ rpe = [ this .( InstanceOfExpr ) .getPattern ( ) , this .( PatternCase ) .getPattern ( ) ]
192+ |
193+ not rpe .isUnrestricted ( )
194+ )
195+ then restricted = true
196+ else restricted = false
197+ )
198+ }
199+
167200 /**
168201 * Holds if the evaluation of this guard to `branch` corresponds to the edge
169202 * from `bb1` to `bb2`.
@@ -223,60 +256,6 @@ class Guard extends ExprParent {
223256 }
224257}
225258
226- /**
227- * A `Guard` that tests an expression's type -- that is, an `instanceof T` or a
228- * `case T varname` pattern case.
229- */
230- class TypeTestGuard extends Guard {
231- Expr testedExpr ;
232- Type testedType ;
233-
234- TypeTestGuard ( ) {
235- exists ( InstanceOfExpr ioe | this = ioe |
236- testedExpr = ioe .getExpr ( ) and
237- testedType = ioe .getSyntacticCheckedType ( )
238- )
239- or
240- exists ( PatternCase pc | this = pc |
241- pc .getSelectorExpr ( ) = testedExpr and
242- testedType = pc .getPattern ( ) .getType ( )
243- )
244- }
245-
246- /**
247- * Gets the record pattern this type test binds to, if any.
248- */
249- PatternExpr getPattern ( ) {
250- result = this .( InstanceOfExpr ) .getPattern ( )
251- or
252- result = this .( PatternCase ) .getPattern ( )
253- }
254-
255- /**
256- * Holds if this guard tests whether `e` has type `t` on `testedBranch`.
257- *
258- * Note that record patterns that make at least one tighter restriction than the record's definition
259- * (e.g. matching `record R(Object)` with `case R(String)`) means this only guarantees the tested type
260- * on the true branch (i.e., entering such a case guarantees `testedExpr` is a `testedType`, but failing
261- * the type test could mean a nested record or binding pattern didn't match but `testedExpr` is still
262- * of type `testedType`.)
263- */
264- predicate appliesTypeTest ( Expr e , Type t , boolean testedBranch ) {
265- e = testedExpr and
266- t = testedType and
267- (
268- testedBranch = true
269- or
270- testedBranch = false and
271- (
272- this .getPattern ( ) .asRecordPattern ( ) .isUnrestricted ( )
273- or
274- not this .getPattern ( ) instanceof RecordPatternExpr
275- )
276- )
277- }
278- }
279-
280259private predicate switchCaseControls ( SwitchCase sc , BasicBlock bb ) {
281260 exists ( BasicBlock caseblock |
282261 caseblock .getFirstNode ( ) = sc .getControlFlowNode ( ) and
0 commit comments