@@ -82,6 +82,7 @@ module;
8282 */
8383
8484import java
85+ private import codeql.util.Boolean
8586private import Completion
8687private import controlflow.internal.Preconditions
8788private import controlflow.internal.SwitchCases
@@ -102,6 +103,7 @@ module ControlFlow {
102103 private newtype TNode =
103104 TExprNode ( Expr e ) { hasControlFlow ( e ) } or
104105 TStmtNode ( Stmt s ) or
106+ TAnnotatedExitNode ( Callable c , Boolean normal ) { exists ( c .getBody ( ) ) } or
105107 TExitNode ( Callable c ) { exists ( c .getBody ( ) ) } or
106108 TAssertThrowNode ( AssertStmt s )
107109
@@ -191,6 +193,38 @@ module ControlFlow {
191193 override Location getLocation ( ) { result = s .getLocation ( ) }
192194 }
193195
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+
194228 /** A control flow node indicating the termination of a callable. */
195229 class ExitNode extends Node , TExitNode {
196230 Callable c ;
@@ -1266,11 +1300,17 @@ private module ControlFlowGraphImpl {
12661300 */
12671301 cached
12681302 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.
12701305 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
12721309 )
12731310 or
1311+ completion = NormalCompletion ( ) and
1312+ n .( AnnotatedExitNode ) .getEnclosingCallable ( ) = result .( ExitNode ) .getEnclosingCallable ( )
1313+ or
12741314 // Logic expressions and conditional expressions execute in AST pre-order.
12751315 completion = NormalCompletion ( ) and
12761316 (
0 commit comments