@@ -85,21 +85,59 @@ module Make<LocationSig Location, CfgSig<Location> Cfg, InputSig<Cfg::AstNode, C
8585{
8686 private import Cfg
8787
88- /** Holds if `n` from `bb` starts at the given line. */
89- private predicate node ( int line , ControlFlowNode n , BasicBlock bb ) {
90- n .injects ( _) and
91- n .getLocation ( ) .getStartLine ( ) = line and
92- n .getBasicBlock ( ) = bb
88+ /**
89+ * Gets the rank of `n` within `bb` restricted to nodes that are canonical
90+ * representatives of AST nodes.
91+ */
92+ private int bbRank ( ControlFlowNode n , BasicBlock bb ) {
93+ n =
94+ rank [ result ] ( ControlFlowNode n0 , int i | n0 .injects ( _) and bb .getNode ( i ) = n0 | n0 order by i )
9395 }
9496
95- /** Gets the rank of `n` within the slice of `bb` at the given line. */
96- private int sliceRank ( int line , ControlFlowNode n , BasicBlock bb ) {
97- n =
98- rank [ result ] ( ControlFlowNode n0 , int i |
99- node ( line , n0 , bb ) and n0 = bb .getNode ( i )
100- |
101- n0 order by i
102- )
97+ /** Gets the start line of `n`. */
98+ private int getLine ( ControlFlowNode n ) { n .getLocation ( ) .getStartLine ( ) = result }
99+
100+ /** Holds if `n` is the first node of a slice of `bb` at the given line. */
101+ private predicate sliceStart ( int line , ControlFlowNode n , BasicBlock bb ) {
102+ line = getLine ( n ) and
103+ 1 = bbRank ( n , bb )
104+ or
105+ exists ( ControlFlowNode n0 |
106+ line = getLine ( n ) and
107+ bbRank ( n0 , bb ) + 1 = bbRank ( n , bb ) and
108+ getLine ( n0 ) != line
109+ )
110+ }
111+
112+ private newtype TSlice =
113+ TMkSlice ( int line , ControlFlowNode n , BasicBlock bb ) { sliceStart ( line , n , bb ) }
114+
115+ /** A slice of a basic block at a specific line. */
116+ private class Slice extends TSlice {
117+ private int line ;
118+ private ControlFlowNode start ;
119+ private BasicBlock bb ;
120+
121+ Slice ( ) { this = TMkSlice ( line , start , bb ) }
122+
123+ string toString ( ) { result = start .toString ( ) }
124+
125+ int getLine ( ) { result = line }
126+
127+ ControlFlowNode getNode ( int i ) {
128+ i = 0 and result = start
129+ or
130+ bbRank ( this .getNode ( i - 1 ) , bb ) + 1 = bbRank ( result , bb ) and
131+ not sliceStart ( _, result , bb )
132+ }
133+
134+ ControlFlowNode getLast ( ) {
135+ exists ( int i | result = this .getNode ( i ) and not exists ( this .getNode ( i + 1 ) ) )
136+ }
137+
138+ predicate step ( ControlFlowNode n1 , ControlFlowNode n2 ) {
139+ exists ( int i | n1 = this .getNode ( i ) and n2 = this .getNode ( i + 1 ) )
140+ }
103141 }
104142
105143 /**
@@ -125,10 +163,10 @@ module Make<LocationSig Location, CfgSig<Location> Cfg, InputSig<Cfg::AstNode, C
125163 * the other. The direction in the AST is given by `dir`.
126164 */
127165 private predicate astUpDownStep ( ControlFlowNode n1 , ControlFlowNode n2 , Dir dir ) {
128- exists ( int line , BasicBlock bb , AstNode a1 , AstNode a2 |
166+ exists ( AstNode a1 , AstNode a2 |
129167 n1 .injects ( a1 ) and
130168 n2 .injects ( a2 ) and
131- sliceRank ( line , n1 , bb ) + 1 = sliceRank ( line , n2 , bb )
169+ any ( Slice s ) . step ( n1 , n2 )
132170 |
133171 if Input:: getParent + ( a1 ) = a2
134172 then dir = Up ( )
@@ -151,14 +189,12 @@ module Make<LocationSig Location, CfgSig<Location> Cfg, InputSig<Cfg::AstNode, C
151189 private predicate oneline ( Location l ) { l .getStartLine ( ) = l .getEndLine ( ) }
152190
153191 /**
154- * Holds if `n1` steps to `n2` within a basic block line slice of `bb` at
155- * `line` and that the step in locations is given by `dir`. Some identical
156- * locations may be further resolved by peeking at the AST structure.
192+ * Holds if `n1` steps to `n2` within a basic block line slice `slice` and
193+ * that the step in locations is given by `dir`. Some identical locations may
194+ * be further resolved by peeking at the AST structure.
157195 */
158- private predicate singleLineBlockStep (
159- BasicBlock bb , int line , ControlFlowNode n1 , ControlFlowNode n2 , Dir dir
160- ) {
161- sliceRank ( line , n1 , bb ) + 1 = sliceRank ( line , n2 , bb ) and
196+ private predicate singleLineBlockStep ( Slice slice , ControlFlowNode n1 , ControlFlowNode n2 , Dir dir ) {
197+ slice .step ( n1 , n2 ) and
162198 exists ( Location l1 , Location l2 | n1 .getLocation ( ) = l1 and n2 .getLocation ( ) = l2 |
163199 if oneline ( l1 ) and l1 .getEndColumn ( ) < l2 .getStartColumn ( )
164200 then dir = Right ( )
@@ -186,28 +222,26 @@ module Make<LocationSig Location, CfgSig<Location> Cfg, InputSig<Cfg::AstNode, C
186222 }
187223
188224 /**
189- * Holds if the `line` slice of the basic block `bb` is simple left-to-right
190- * evaluation order.
225+ * Holds if the slice `slice` is simple left-to-right evaluation order.
191226 *
192227 * Both pre-order and post-order traversal is allowed and allowed to be
193228 * mixed. `Up` indicates the last part of a post-order traversal, and `Down`
194229 * indicates the first part of a pre-order traversal, so an `Up` step
195230 * followed by a `Down` step is inconsistent with simple left-to-right
196231 * evaluation order.
197232 */
198- private predicate simpleLeftToRightBlock ( int line , BasicBlock bb ) {
199- node ( line , _, bb ) and
200- forall ( ControlFlowNode n1 , ControlFlowNode n2 | singleLineBlockStep ( bb , line , n1 , n2 , _) |
201- exists ( Dir dir | singleLineBlockStep ( bb , line , n1 , n2 , dir ) |
233+ private predicate simpleLeftToRightBlock ( Slice slice ) {
234+ forall ( ControlFlowNode n1 , ControlFlowNode n2 | singleLineBlockStep ( slice , n1 , n2 , _) |
235+ exists ( Dir dir | singleLineBlockStep ( slice , n1 , n2 , dir ) |
202236 dir != Other ( ) and
203237 dir != Id ( ) and
204- ( dir = Up ( ) implies not singleLineBlockStep ( bb , line , n2 , _, Down ( ) ) )
238+ ( dir = Up ( ) implies not singleLineBlockStep ( slice , n2 , _, Down ( ) ) )
205239 )
206240 )
207241 }
208242
209243 private string outgoingArrow ( ControlFlowNode n ) {
210- exists ( Dir dir | singleLineBlockStep ( _, _ , n , _, dir ) |
244+ exists ( Dir dir | singleLineBlockStep ( _, n , _, dir ) |
211245 dir = Down ( ) and result = " -V "
212246 or
213247 dir = Up ( ) and result = " -^ "
@@ -222,23 +256,24 @@ module Make<LocationSig Location, CfgSig<Location> Cfg, InputSig<Cfg::AstNode, C
222256
223257 module BlockSlices {
224258 /**
225- * Holds if `blockSlice` is a string representation of the `line` slice of a
259+ * Holds if `blockSlice` is a string representation of a `line` slice of a
226260 * basic block. `first` is the first node in the slice.
227261 */
228262 query predicate blockSlice ( int line , ControlFlowNode first , string blockSlice ) {
229- exists ( BasicBlock bb |
230- 1 = sliceRank ( line , first , bb ) and
263+ exists ( Slice slice |
264+ first = slice .getNode ( 0 ) and
265+ line = slice .getLine ( ) and
231266 blockSlice =
232267 "'" +
233- strictconcat ( ControlFlowNode n , int r , int i , string s |
234- r = sliceRank ( line , n , bb ) and
268+ strictconcat ( ControlFlowNode n , int i , int j , string s |
269+ slice . getNode ( i ) = n and
235270 (
236- i = 0 and s = n .toString ( )
271+ j = 0 and s = n .toString ( )
237272 or
238- i = 1 and s = outgoingArrow ( n )
273+ j = 1 and s = outgoingArrow ( n )
239274 )
240275 |
241- s order by r , i
276+ s order by i , j
242277 ) + "'"
243278 )
244279 }
@@ -262,22 +297,13 @@ module Make<LocationSig Location, CfgSig<Location> Cfg, InputSig<Cfg::AstNode, C
262297 * `first` is the first node in the slice.
263298 */
264299 query predicate nonSimple ( ControlFlowNode1line first , string blockSlice ) {
265- exists ( int line , BasicBlock bb |
266- BlockSlices:: blockSlice ( line , first , blockSlice ) and
267- bb = first . getBasicBlock ( ) and
268- not simpleLeftToRightBlock ( line , bb )
300+ exists ( Slice slice |
301+ BlockSlices:: blockSlice ( _ , first , blockSlice ) and
302+ slice . getNode ( 0 ) = first and
303+ not simpleLeftToRightBlock ( slice )
269304 )
270305 }
271306
272- /**
273- * Gets the rank of `n` within `bb` restricted to nodes that are canonical
274- * representatives of AST nodes.
275- */
276- private int bbRank ( ControlFlowNode n , BasicBlock bb ) {
277- n =
278- rank [ result ] ( ControlFlowNode n0 , int i | n0 .injects ( _) and bb .getNode ( i ) = n0 | n0 order by i )
279- }
280-
281307 /**
282308 * Holds if some AST node on `line` has a corresponding CFG node within the
283309 * callable `c`.
@@ -303,9 +329,8 @@ module Make<LocationSig Location, CfgSig<Location> Cfg, InputSig<Cfg::AstNode, C
303329 int line , ControlFlowNode n1 , ControlFlowNode n2 , int lineDelta
304330 ) {
305331 line = n1 .getLocation ( ) .getStartLine ( ) and
306- exists ( int last , BasicBlock bb |
307- last = sliceRank ( line , n1 , bb ) and
308- not last + 1 = sliceRank ( line , _, bb ) and
332+ exists ( BasicBlock bb |
333+ n1 = any ( Slice slice ) .getLast ( ) and
309334 bbRank ( n1 , bb ) + 1 = bbRank ( n2 , bb )
310335 ) and
311336 lineDelta = n2 .getLocation ( ) .getStartLine ( ) - n1 .getLocation ( ) .getStartLine ( ) and
0 commit comments