8080 */
8181
8282import java
83+ private import codeql.util.Boolean
8384private import Completion
8485private import controlflow.internal.Preconditions
8586private import controlflow.internal.SwitchCases
@@ -100,6 +101,7 @@ module ControlFlow {
100101 private newtype TNode =
101102 TExprNode ( Expr e ) { hasControlFlow ( e ) } or
102103 TStmtNode ( Stmt s ) or
104+ TAnnotatedExitNode ( Callable c , Boolean normal ) { exists ( c .getBody ( ) ) } or
103105 TExitNode ( Callable c ) { exists ( c .getBody ( ) ) } or
104106 TAssertThrowNode ( AssertStmt s )
105107
@@ -189,6 +191,38 @@ module ControlFlow {
189191 override Location getLocation ( ) { result = s .getLocation ( ) }
190192 }
191193
194+ /** A control flow node indicating the normal or exceptional termination of a callable. */
195+ class AnnotatedExitNode extends Node , TAnnotatedExitNode {
196+ Callable c ;
197+ boolean normal ;
198+
199+ AnnotatedExitNode ( ) { this = TAnnotatedExitNode ( c , normal ) }
200+
201+ override Callable getEnclosingCallable ( ) { result = c }
202+
203+ override ExprParent getAstNode ( ) { result = c }
204+
205+ /** Gets a textual representation of this element. */
206+ override string toString ( ) {
207+ normal = true and result = "Normal Exit"
208+ or
209+ normal = false and result = "Exceptional Exit"
210+ }
211+
212+ /** Gets the source location for this element. */
213+ override Location getLocation ( ) { result = c .getLocation ( ) }
214+ }
215+
216+ /** A control flow node indicating normal termination of a callable. */
217+ class NormalExitNode extends AnnotatedExitNode {
218+ NormalExitNode ( ) { this = TAnnotatedExitNode ( _, true ) }
219+ }
220+
221+ /** A control flow node indicating exceptional termination of a callable. */
222+ class ExceptionalExitNode extends AnnotatedExitNode {
223+ ExceptionalExitNode ( ) { this = TAnnotatedExitNode ( _, false ) }
224+ }
225+
192226 /** A control flow node indicating the termination of a callable. */
193227 class ExitNode extends Node , TExitNode {
194228 Callable c ;
@@ -1264,11 +1298,17 @@ private module ControlFlowGraphImpl {
12641298 */
12651299 cached
12661300 Node succ ( Node n , Completion completion ) {
1267- // After executing the callable body, the final node is the exit node.
1301+ // After executing the callable body, the final nodes are first the
1302+ // annotated exit node and then the final exit node.
12681303 exists ( Callable c | last ( c .getBody ( ) , n , completion ) |
1269- result .( ExitNode ) .getEnclosingCallable ( ) = c
1304+ if completion instanceof ThrowCompletion
1305+ then result .( ExceptionalExitNode ) .getEnclosingCallable ( ) = c
1306+ else result .( NormalExitNode ) .getEnclosingCallable ( ) = c
12701307 )
12711308 or
1309+ completion = NormalCompletion ( ) and
1310+ n .( AnnotatedExitNode ) .getEnclosingCallable ( ) = result .( ExitNode ) .getEnclosingCallable ( )
1311+ or
12721312 // Logic expressions and conditional expressions execute in AST pre-order.
12731313 completion = NormalCompletion ( ) and
12741314 (
0 commit comments