@@ -82,6 +82,7 @@ module;
82
82
*/
83
83
84
84
import java
85
+ private import codeql.util.Boolean
85
86
private import Completion
86
87
private import controlflow.internal.Preconditions
87
88
private import controlflow.internal.SwitchCases
@@ -102,6 +103,7 @@ module ControlFlow {
102
103
private newtype TNode =
103
104
TExprNode ( Expr e ) { hasControlFlow ( e ) } or
104
105
TStmtNode ( Stmt s ) or
106
+ TAnnotatedExitNode ( Callable c , Boolean normal ) { exists ( c .getBody ( ) ) } or
105
107
TExitNode ( Callable c ) { exists ( c .getBody ( ) ) } or
106
108
TAssertThrowNode ( AssertStmt s )
107
109
@@ -191,6 +193,38 @@ module ControlFlow {
191
193
override Location getLocation ( ) { result = s .getLocation ( ) }
192
194
}
193
195
196
+ /** A control flow node indicating the normal or exceptional termination of a callable. */
197
+ class AnnotatedExitNode extends Node , TAnnotatedExitNode {
198
+ Callable c ;
199
+ boolean normal ;
200
+
201
+ AnnotatedExitNode ( ) { this = TAnnotatedExitNode ( c , normal ) }
202
+
203
+ override Callable getEnclosingCallable ( ) { result = c }
204
+
205
+ override ExprParent getAstNode ( ) { result = c }
206
+
207
+ /** Gets a textual representation of this element. */
208
+ override string toString ( ) {
209
+ normal = true and result = "Normal Exit"
210
+ or
211
+ normal = false and result = "Exceptional Exit"
212
+ }
213
+
214
+ /** Gets the source location for this element. */
215
+ override Location getLocation ( ) { result = c .getLocation ( ) }
216
+ }
217
+
218
+ /** A control flow node indicating normal termination of a callable. */
219
+ class NormalExitNode extends AnnotatedExitNode {
220
+ NormalExitNode ( ) { this = TAnnotatedExitNode ( _, true ) }
221
+ }
222
+
223
+ /** A control flow node indicating exceptional termination of a callable. */
224
+ class ExceptionalExitNode extends AnnotatedExitNode {
225
+ ExceptionalExitNode ( ) { this = TAnnotatedExitNode ( _, false ) }
226
+ }
227
+
194
228
/** A control flow node indicating the termination of a callable. */
195
229
class ExitNode extends Node , TExitNode {
196
230
Callable c ;
@@ -1266,11 +1300,17 @@ private module ControlFlowGraphImpl {
1266
1300
*/
1267
1301
cached
1268
1302
Node succ ( Node n , Completion completion ) {
1269
- // After executing the callable body, the final node is the exit node.
1303
+ // After executing the callable body, the final nodes are first the
1304
+ // annotated exit node and then the final exit node.
1270
1305
exists ( Callable c | last ( c .getBody ( ) , n , completion ) |
1271
- result .( ExitNode ) .getEnclosingCallable ( ) = c
1306
+ if completion instanceof ThrowCompletion
1307
+ then result .( ExceptionalExitNode ) .getEnclosingCallable ( ) = c
1308
+ else result .( NormalExitNode ) .getEnclosingCallable ( ) = c
1272
1309
)
1273
1310
or
1311
+ completion = NormalCompletion ( ) and
1312
+ n .( AnnotatedExitNode ) .getEnclosingCallable ( ) = result .( ExitNode ) .getEnclosingCallable ( )
1313
+ or
1274
1314
// Logic expressions and conditional expressions execute in AST pre-order.
1275
1315
completion = NormalCompletion ( ) and
1276
1316
(
0 commit comments