1+ // NOTE: There are two copies of this file, and they must be kept identical:
2+ // - semmle/code/cpp/controlflow/SubBasicBlocks.qll
3+ // - semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll
14//
2- // NOTE: Maintain this file in synchrony with
3- // semmlecode-cpp-queries/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll
4- //
5+ // The second one is a private copy of the `SubBasicBlocks` library for
6+ // internal use by the data flow library. Having an extra copy prevents
7+ // non-monotonic recursion errors in queries that use both the data flow
8+ // library and the `SubBasicBlocks` library.
59
610/**
711 * Provides the `SubBasicBlock` class, used for partitioning basic blocks in
@@ -71,14 +75,18 @@ class SubBasicBlock extends ControlFlowNodeBase {
7175 * `bb`, where `bb` is equal to `getBasicBlock()`.
7276 */
7377 int getPosInBasicBlock ( BasicBlock bb ) {
74- exists ( int nodePos , int rnk |
75- bb = this .( ControlFlowNode ) .getBasicBlock ( ) and
76- this = bb .getNode ( nodePos ) and
77- nodePos = rank [ rnk ] ( int i | exists ( SubBasicBlock n | n = bb .getNode ( i ) ) ) and
78+ exists ( int thisIndexInBB , int rnk |
79+ thisIndexInBB = this .getIndexInBasicBlock ( bb ) and
80+ thisIndexInBB = rank [ rnk ] ( int i | i = any ( SubBasicBlock n ) .getIndexInBasicBlock ( bb ) ) and
7881 result = rnk - 1
7982 )
8083 }
8184
85+ pragma [ noinline]
86+ private int getIndexInBasicBlock ( BasicBlock bb ) {
87+ this = bb .getNode ( result )
88+ }
89+
8290 /** Gets a successor in the control-flow graph of `SubBasicBlock`s. */
8391 SubBasicBlock getASuccessor ( ) {
8492 this .lastInBB ( ) and
@@ -94,16 +102,22 @@ class SubBasicBlock extends ControlFlowNodeBase {
94102 * start from 0, and the node at position 0 always exists and compares equal
95103 * to `this`.
96104 */
105+ pragma [ nomagic]
97106 ControlFlowNode getNode ( int pos ) {
98- exists ( BasicBlock bb | bb = this .getBasicBlock ( ) |
99- exists ( int thisPos | this = bb .getNode ( thisPos ) |
100- result = bb .getNode ( thisPos + pos ) and
101- pos >= 0 and
102- pos < this .getNumberOfNodes ( )
107+ exists ( BasicBlock bb |
108+ exists ( int outerPos |
109+ result = bb .getNode ( outerPos ) and
110+ pos = outerPosToInnerPos ( bb , outerPos )
103111 )
104112 )
105113 }
106114
115+ pragma [ nomagic]
116+ private int outerPosToInnerPos ( BasicBlock bb , int posInBB ) {
117+ posInBB = result + this .getIndexInBasicBlock ( bb ) and
118+ result = [ 0 .. this .getNumberOfNodes ( ) - 1 ]
119+ }
120+
107121 /** Gets a control-flow node in this `SubBasicBlock`. */
108122 ControlFlowNode getANode ( ) {
109123 result = this .getNode ( _)
@@ -143,14 +157,20 @@ class SubBasicBlock extends ControlFlowNodeBase {
143157 * Gets the number of control-flow nodes in this `SubBasicBlock`. There is
144158 * always at least one.
145159 */
160+ pragma [ noopt]
146161 int getNumberOfNodes ( ) {
147162 exists ( BasicBlock bb | bb = this .getBasicBlock ( ) |
148163 exists ( int thisPos | this = bb .getNode ( thisPos ) |
149- this .lastInBB ( ) and
150- result = bb .length ( ) - thisPos
164+ exists ( int bbLength |
165+ this .lastInBB ( ) and
166+ bbLength = bb .length ( ) and
167+ result = bbLength - thisPos
168+ )
151169 or
152- exists ( SubBasicBlock succ , int succPos |
153- succ .getPosInBasicBlock ( bb ) = this .getPosInBasicBlock ( bb ) + 1 and
170+ exists ( SubBasicBlock succ , int succPos , int thisRank , int succRank |
171+ thisRank = this .getPosInBasicBlock ( bb ) and
172+ succRank = thisRank + 1 and
173+ succRank = succ .getPosInBasicBlock ( bb ) and
154174 bb .getNode ( succPos ) = succ and
155175 result = succPos - thisPos
156176 )
0 commit comments