@@ -143,14 +143,40 @@ module LocalFlow {
143143 SsaImpl:: adjacentReadPairExt ( def , nodeFrom .asExpr ( ) , nodeTo .asExpr ( ) )
144144 }
145145
146+ /**
147+ * Holds if SSA definition `def` assigns `value` to the underlying variable.
148+ *
149+ * This is either a direct assignment, `x = value`, or an assignment via
150+ * simple pattern matching
151+ *
152+ * ```rb
153+ * case value
154+ * in Foo => x then ...
155+ * in y => then ...
156+ * end
157+ * ```
158+ */
159+ predicate ssaDefAssigns ( Ssa:: WriteDefinition def , CfgNodes:: ExprCfgNode value ) {
160+ def .assigns ( value )
161+ or
162+ exists ( CfgNodes:: ExprNodes:: CaseExprCfgNode case , CfgNodes:: AstCfgNode pattern |
163+ case .getValue ( ) = value and
164+ pattern = case .getBranch ( _) .( CfgNodes:: ExprNodes:: InClauseCfgNode ) .getPattern ( )
165+ |
166+ def .getWriteAccess ( ) = pattern
167+ or
168+ def .getWriteAccess ( ) = pattern .( CfgNodes:: ExprNodes:: AsPatternCfgNode ) .getVariableAccess ( )
169+ )
170+ }
171+
146172 /**
147173 * Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
148174 * SSA definition `def`.
149175 */
150176 pragma [ nomagic]
151177 predicate localSsaFlowStep ( SsaImpl:: DefinitionExt def , Node nodeFrom , Node nodeTo ) {
152178 // Flow from assignment into SSA definition
153- def . ( Ssa :: WriteDefinition ) . assigns ( nodeFrom .asExpr ( ) ) and
179+ ssaDefAssigns ( def , nodeFrom .asExpr ( ) ) and
154180 nodeTo .( SsaDefinitionExtNode ) .getDefinitionExt ( ) = def
155181 or
156182 // Flow from SSA definition to first read
@@ -273,7 +299,7 @@ module VariableCapture {
273299 or
274300 exists ( Ssa:: Definition def |
275301 def .getARead ( ) = e2 and
276- def .getAnUltimateDefinition ( ) . ( Ssa :: WriteDefinition ) . assigns ( e1 )
302+ LocalFlow :: ssaDefAssigns ( def .getAnUltimateDefinition ( ) , e1 )
277303 )
278304 }
279305
@@ -574,8 +600,7 @@ private module Cached {
574600
575601 /** Holds if `n` wraps an SSA definition without ingoing flow. */
576602 private predicate entrySsaDefinition ( SsaDefinitionExtNode n ) {
577- n .getDefinitionExt ( ) =
578- any ( SsaImpl:: WriteDefinition def | not def .( Ssa:: WriteDefinition ) .assigns ( _) )
603+ n .getDefinitionExt ( ) = any ( SsaImpl:: WriteDefinition def | not LocalFlow:: ssaDefAssigns ( def , _) )
579604 }
580605
581606 pragma [ nomagic]
0 commit comments