Skip to content

Commit acea4dd

Browse files
committed
C#: Introduce control flow exit completions
1 parent 0c1db6a commit acea4dd

File tree

8 files changed

+114
-81
lines changed

8 files changed

+114
-81
lines changed

csharp/ql/src/semmle/code/csharp/controlflow/Completion.qll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ private newtype TCompletion =
5959
TGotoDefaultCompletion()
6060
or
6161
TThrowCompletion(ExceptionClass ec)
62+
or
63+
TExitCompletion()
6264

6365
/**
6466
* A completion of a statement or an expression.
@@ -642,3 +644,16 @@ class ThrowCompletion extends Completion, TThrowCompletion {
642644

643645
override string toString() { result = "throw(" + getExceptionClass() + ")" }
644646
}
647+
648+
/**
649+
* A completion that represents evaluation of a statement or an
650+
* expression resulting in a program exit, for example
651+
* `System.Environment.Exit(0)`.
652+
*
653+
* An exit completion is different from a `return` completion; the former
654+
* exits the whole application, and exists inside `try` statements skip
655+
* `finally` blocks.
656+
*/
657+
class ExitCompletion extends Completion, TExitCompletion {
658+
override string toString() { result = "exit" }
659+
}

csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll

Lines changed: 72 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,30 @@ module ControlFlow {
785785
c.(ThrowCompletion).getExceptionClass() = getExceptionClass()
786786
}
787787
}
788+
789+
/**
790+
* An exit control flow successor.
791+
*
792+
* Example:
793+
*
794+
* ```
795+
* int M(string s)
796+
* {
797+
* if (s == null)
798+
* System.Environment.Exit(0);
799+
* return s.Length;
800+
* }
801+
* ```
802+
*
803+
* The callable exit node of `M` is an exit successor of the node on line 4.
804+
*/
805+
class ExitSuccessor extends SuccessorType, TExitSuccessor {
806+
override string toString() { result = "exit" }
807+
808+
override predicate matchesCompletion(Completion c) {
809+
c instanceof ExitCompletion
810+
}
811+
}
788812
}
789813
private import SuccessorTypes
790814

@@ -1386,10 +1410,15 @@ module ControlFlow {
13861410
result = lastTryStmtFinally(ts, c) and
13871411
not c instanceof NormalCompletion
13881412
or
1389-
// If there is no `finally` block, last elements are from the body, from
1390-
// the blocks of one of the `catch` clauses, or from the last `catch` clause
1391-
not ts.hasFinally() and
1392-
result = getBlockOrCatchFinallyPred(ts, c)
1413+
result = getBlockOrCatchFinallyPred(ts, c) and
1414+
(
1415+
// If there is no `finally` block, last elements are from the body, from
1416+
// the blocks of one of the `catch` clauses, or from the last `catch` clause
1417+
not ts.hasFinally()
1418+
or
1419+
// Exit completions ignore the `finally` block
1420+
c instanceof ExitCompletion
1421+
)
13931422
)
13941423
or
13951424
cfe = any(SpecificCatchClause scc |
@@ -1453,7 +1482,7 @@ module ControlFlow {
14531482
// Propagate completion from a call to a non-terminating callable
14541483
cfe = any(NonReturningCall nrc |
14551484
result = nrc and
1456-
c = nrc.getTarget().(NonReturningCallable).getACallCompletion()
1485+
c = nrc.getACompletion()
14571486
)
14581487
}
14591488

@@ -1736,17 +1765,31 @@ module ControlFlow {
17361765
private import semmle.code.csharp.ExprOrStmtParent
17371766
private import semmle.code.csharp.frameworks.System
17381767

1739-
/**
1740-
* A call that definitely does not return (conservative analysis).
1741-
*/
1742-
class NonReturningCall extends Call {
1743-
NonReturningCall() {
1744-
this.getTarget() instanceof NonReturningCallable
1768+
/** A call that definitely does not return (conservative analysis). */
1769+
abstract class NonReturningCall extends Call {
1770+
/** Gets a valid completion for this non-returning call. */
1771+
abstract Completion getACompletion();
1772+
}
1773+
1774+
private class ExitingCall extends NonReturningCall {
1775+
ExitingCall() {
1776+
this.getTarget() instanceof ExitingCallable
17451777
}
1778+
1779+
override ExitCompletion getACompletion() { any() }
17461780
}
17471781

1748-
/** A callable that does not return. */
1749-
abstract class NonReturningCallable extends Callable {
1782+
private class ThrowingCall extends NonReturningCall {
1783+
private ThrowCompletion c;
1784+
1785+
ThrowingCall() {
1786+
c = this.getTarget().(ThrowingCallable).getACallCompletion()
1787+
}
1788+
1789+
override ThrowCompletion getACompletion() { result = c }
1790+
}
1791+
1792+
private abstract class NonReturningCallable extends Callable {
17501793
NonReturningCallable() {
17511794
not exists(ReturnStmt ret | ret.getEnclosingCallable() = this) and
17521795
not hasAccessorAutoImplementation(this, _) and
@@ -1756,19 +1799,9 @@ module ControlFlow {
17561799
v = this.(Accessor).getDeclaration()
17571800
)
17581801
}
1759-
1760-
/** Gets a valid completion for a call to this non-returning callable. */
1761-
abstract Completion getACallCompletion();
17621802
}
17631803

1764-
/**
1765-
* A callable that exits when called.
1766-
*/
1767-
private abstract class ExitingCallable extends NonReturningCallable {
1768-
override Completion getACallCompletion() {
1769-
result instanceof ReturnCompletion
1770-
}
1771-
}
1804+
private abstract class ExitingCallable extends NonReturningCallable { }
17721805

17731806
private class DirectlyExitingCallable extends ExitingCallable {
17741807
DirectlyExitingCallable() {
@@ -1789,7 +1822,8 @@ module ControlFlow {
17891822
}
17901823

17911824
private ControlFlowElement getAnExitingElement() {
1792-
result.(Call).getTarget() instanceof ExitingCallable or
1825+
result instanceof ExitingCall
1826+
or
17931827
result = getAnExitingStmt()
17941828
}
17951829

@@ -1805,9 +1839,6 @@ module ControlFlow {
18051839
)
18061840
}
18071841

1808-
/**
1809-
* A callable that throws an exception when called.
1810-
*/
18111842
private class ThrowingCallable extends NonReturningCallable {
18121843
ThrowingCallable() {
18131844
forex(ControlFlowElement body |
@@ -1816,16 +1847,17 @@ module ControlFlow {
18161847
)
18171848
}
18181849

1819-
override ThrowCompletion getACallCompletion() {
1850+
/** Gets a valid completion for a call to this throwing callable. */
1851+
ThrowCompletion getACallCompletion() {
18201852
this.getABody() = getAThrowingElement(result)
18211853
}
18221854
}
18231855

18241856
private ControlFlowElement getAThrowingElement(ThrowCompletion c) {
1825-
c = result.(Call).getTarget().(ThrowingCallable).getACallCompletion()
1857+
c = result.(ThrowingCall).getACompletion()
18261858
or
18271859
result = any(ThrowElement te |
1828-
c.(ThrowCompletion).getExceptionClass() = te.getThrownExceptionType() and
1860+
c.getExceptionClass() = te.getThrownExceptionType() and
18291861
// For stub implementations, there may exist proper implementations that are not seen
18301862
// during compilation, so we conservatively rule those out
18311863
not isStub(te)
@@ -1839,12 +1871,13 @@ module ControlFlow {
18391871
or
18401872
result.(BlockStmt).getFirstStmt() = getAThrowingStmt(c)
18411873
or
1842-
exists(IfStmt ifStmt |
1874+
exists(IfStmt ifStmt, ThrowCompletion c1, ThrowCompletion c2 |
18431875
result = ifStmt and
1844-
ifStmt.getThen() = getAThrowingElement(_) and
1845-
ifStmt.getElse() = getAThrowingElement(_) |
1846-
ifStmt.getThen() = getAThrowingElement(c) or
1847-
ifStmt.getElse() = getAThrowingElement(c)
1876+
ifStmt.getThen() = getAThrowingElement(c1) and
1877+
ifStmt.getElse() = getAThrowingElement(c2) |
1878+
c = c1
1879+
or
1880+
c = c2
18481881
)
18491882
}
18501883

@@ -2293,6 +2326,7 @@ module ControlFlow {
22932326
// Flow from last element of `try` block to first element of `finally` block
22942327
cfe = lastTryStmtBlock(ts, c) and
22952328
result = first(ts.getFinally()) and
2329+
not c instanceof ExitCompletion and
22962330
(
22972331
c instanceof ThrowCompletion
22982332
implies
@@ -3892,6 +3926,8 @@ module ControlFlow {
38923926
TExceptionSuccessor(ExceptionClass ec) {
38933927
exists(ThrowCompletion c | c.getExceptionClass() = ec)
38943928
}
3929+
or
3930+
TExitSuccessor()
38953931

38963932
/** Gets a successor node of a given flow type, if any. */
38973933
cached

csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@
183183
| ExitMethods.cs:62:19:62:33 | object creation of type Exception | ExitMethods.cs:62:13:62:34 | throw ...; | 2 |
184184
| ExitMethods.cs:64:41:64:43 | "b" | ExitMethods.cs:64:13:64:45 | throw ...; | 3 |
185185
| ExitMethods.cs:67:10:67:13 | enter Exit | ExitMethods.cs:67:10:67:13 | exit Exit | 6 |
186-
| ExitMethods.cs:72:10:72:18 | enter ExitInTry | ExitMethods.cs:72:10:72:18 | exit ExitInTry | 12 |
186+
| ExitMethods.cs:72:10:72:18 | enter ExitInTry | ExitMethods.cs:72:10:72:18 | exit ExitInTry | 8 |
187187
| ExitMethods.cs:85:10:85:24 | enter ApplicationExit | ExitMethods.cs:85:10:85:24 | exit ApplicationExit | 5 |
188188
| ExitMethods.cs:90:13:90:21 | enter ThrowExpr | ExitMethods.cs:92:16:92:25 | ... != ... | 7 |
189189
| ExitMethods.cs:90:13:90:21 | exit ThrowExpr | ExitMethods.cs:90:13:90:21 | exit ThrowExpr | 1 |

csharp/ql/test/library-tests/controlflow/graph/Dominance.expected

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -679,17 +679,13 @@
679679
| post | ExitMethods.cs:69:9:69:27 | call to method Exit | ExitMethods.cs:69:26:69:26 | 0 |
680680
| post | ExitMethods.cs:69:9:69:28 | ...; | ExitMethods.cs:68:5:70:5 | {...} |
681681
| post | ExitMethods.cs:69:26:69:26 | 0 | ExitMethods.cs:69:9:69:28 | ...; |
682-
| post | ExitMethods.cs:72:10:72:18 | exit ExitInTry | ExitMethods.cs:81:13:81:40 | [finally: return] call to method WriteLine |
682+
| post | ExitMethods.cs:72:10:72:18 | exit ExitInTry | ExitMethods.cs:76:13:76:18 | call to method Exit |
683683
| post | ExitMethods.cs:73:5:83:5 | {...} | ExitMethods.cs:72:10:72:18 | enter ExitInTry |
684684
| post | ExitMethods.cs:74:9:82:9 | try {...} ... | ExitMethods.cs:73:5:83:5 | {...} |
685685
| post | ExitMethods.cs:75:9:77:9 | {...} | ExitMethods.cs:74:9:82:9 | try {...} ... |
686686
| post | ExitMethods.cs:76:13:76:18 | call to method Exit | ExitMethods.cs:76:13:76:18 | this access |
687687
| post | ExitMethods.cs:76:13:76:18 | this access | ExitMethods.cs:76:13:76:19 | ...; |
688688
| post | ExitMethods.cs:76:13:76:19 | ...; | ExitMethods.cs:75:9:77:9 | {...} |
689-
| post | ExitMethods.cs:79:9:82:9 | [finally: return] {...} | ExitMethods.cs:76:13:76:18 | call to method Exit |
690-
| post | ExitMethods.cs:81:13:81:40 | [finally: return] call to method WriteLine | ExitMethods.cs:81:38:81:39 | [finally: return] "" |
691-
| post | ExitMethods.cs:81:13:81:41 | [finally: return] ...; | ExitMethods.cs:79:9:82:9 | [finally: return] {...} |
692-
| post | ExitMethods.cs:81:38:81:39 | [finally: return] "" | ExitMethods.cs:81:13:81:41 | [finally: return] ...; |
693689
| post | ExitMethods.cs:85:10:85:24 | exit ApplicationExit | ExitMethods.cs:87:9:87:47 | call to method Exit |
694690
| post | ExitMethods.cs:86:5:88:5 | {...} | ExitMethods.cs:85:10:85:24 | enter ApplicationExit |
695691
| post | ExitMethods.cs:87:9:87:47 | call to method Exit | ExitMethods.cs:87:9:87:48 | ...; |
@@ -2826,13 +2822,9 @@
28262822
| pre | ExitMethods.cs:73:5:83:5 | {...} | ExitMethods.cs:74:9:82:9 | try {...} ... |
28272823
| pre | ExitMethods.cs:74:9:82:9 | try {...} ... | ExitMethods.cs:75:9:77:9 | {...} |
28282824
| pre | ExitMethods.cs:75:9:77:9 | {...} | ExitMethods.cs:76:13:76:19 | ...; |
2829-
| pre | ExitMethods.cs:76:13:76:18 | call to method Exit | ExitMethods.cs:79:9:82:9 | [finally: return] {...} |
2825+
| pre | ExitMethods.cs:76:13:76:18 | call to method Exit | ExitMethods.cs:72:10:72:18 | exit ExitInTry |
28302826
| pre | ExitMethods.cs:76:13:76:18 | this access | ExitMethods.cs:76:13:76:18 | call to method Exit |
28312827
| pre | ExitMethods.cs:76:13:76:19 | ...; | ExitMethods.cs:76:13:76:18 | this access |
2832-
| pre | ExitMethods.cs:79:9:82:9 | [finally: return] {...} | ExitMethods.cs:81:13:81:41 | [finally: return] ...; |
2833-
| pre | ExitMethods.cs:81:13:81:40 | [finally: return] call to method WriteLine | ExitMethods.cs:72:10:72:18 | exit ExitInTry |
2834-
| pre | ExitMethods.cs:81:13:81:41 | [finally: return] ...; | ExitMethods.cs:81:38:81:39 | [finally: return] "" |
2835-
| pre | ExitMethods.cs:81:38:81:39 | [finally: return] "" | ExitMethods.cs:81:13:81:40 | [finally: return] call to method WriteLine |
28362828
| pre | ExitMethods.cs:85:10:85:24 | enter ApplicationExit | ExitMethods.cs:86:5:88:5 | {...} |
28372829
| pre | ExitMethods.cs:86:5:88:5 | {...} | ExitMethods.cs:87:9:87:48 | ...; |
28382830
| pre | ExitMethods.cs:87:9:87:47 | call to method Exit | ExitMethods.cs:85:10:85:24 | exit ApplicationExit |

csharp/ql/test/library-tests/controlflow/graph/ElementGraph.expected

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -520,12 +520,8 @@
520520
| ExitMethods.cs:73:5:83:5 | {...} | ExitMethods.cs:74:9:82:9 | try {...} ... | semmle.label | successor |
521521
| ExitMethods.cs:74:9:82:9 | try {...} ... | ExitMethods.cs:75:9:77:9 | {...} | semmle.label | successor |
522522
| ExitMethods.cs:75:9:77:9 | {...} | ExitMethods.cs:76:13:76:19 | ...; | semmle.label | successor |
523-
| ExitMethods.cs:76:13:76:18 | call to method Exit | ExitMethods.cs:79:9:82:9 | {...} | semmle.label | return |
524523
| ExitMethods.cs:76:13:76:18 | this access | ExitMethods.cs:76:13:76:18 | call to method Exit | semmle.label | successor |
525524
| ExitMethods.cs:76:13:76:19 | ...; | ExitMethods.cs:76:13:76:18 | this access | semmle.label | successor |
526-
| ExitMethods.cs:79:9:82:9 | {...} | ExitMethods.cs:81:13:81:41 | ...; | semmle.label | successor |
527-
| ExitMethods.cs:81:13:81:41 | ...; | ExitMethods.cs:81:38:81:39 | "" | semmle.label | successor |
528-
| ExitMethods.cs:81:38:81:39 | "" | ExitMethods.cs:81:13:81:40 | call to method WriteLine | semmle.label | successor |
529525
| ExitMethods.cs:86:5:88:5 | {...} | ExitMethods.cs:87:9:87:48 | ...; | semmle.label | successor |
530526
| ExitMethods.cs:87:9:87:48 | ...; | ExitMethods.cs:87:9:87:47 | call to method Exit | semmle.label | successor |
531527
| ExitMethods.cs:91:5:93:5 | {...} | ExitMethods.cs:92:16:92:76 | ... ? ... : ... | semmle.label | successor |

csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -691,17 +691,17 @@
691691
| ExitMethods.cs:21:9:21:26 | ...; | ExitMethods.cs:21:9:21:25 | call to method ErrorAlways | throw(Exception) |
692692
| ExitMethods.cs:21:21:21:24 | true | ExitMethods.cs:21:21:21:24 | true | normal |
693693
| ExitMethods.cs:22:9:22:15 | return ...; | ExitMethods.cs:22:9:22:15 | return ...; | return |
694-
| ExitMethods.cs:26:5:29:5 | {...} | ExitMethods.cs:27:9:27:14 | call to method Exit | return |
694+
| ExitMethods.cs:26:5:29:5 | {...} | ExitMethods.cs:27:9:27:14 | call to method Exit | exit |
695695
| ExitMethods.cs:26:5:29:5 | {...} | ExitMethods.cs:28:9:28:15 | return ...; | return |
696-
| ExitMethods.cs:27:9:27:14 | call to method Exit | ExitMethods.cs:27:9:27:14 | call to method Exit | return |
696+
| ExitMethods.cs:27:9:27:14 | call to method Exit | ExitMethods.cs:27:9:27:14 | call to method Exit | exit |
697697
| ExitMethods.cs:27:9:27:14 | this access | ExitMethods.cs:27:9:27:14 | this access | normal |
698-
| ExitMethods.cs:27:9:27:15 | ...; | ExitMethods.cs:27:9:27:14 | call to method Exit | return |
698+
| ExitMethods.cs:27:9:27:15 | ...; | ExitMethods.cs:27:9:27:14 | call to method Exit | exit |
699699
| ExitMethods.cs:28:9:28:15 | return ...; | ExitMethods.cs:28:9:28:15 | return ...; | return |
700-
| ExitMethods.cs:32:5:35:5 | {...} | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | return |
700+
| ExitMethods.cs:32:5:35:5 | {...} | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | exit |
701701
| ExitMethods.cs:32:5:35:5 | {...} | ExitMethods.cs:34:9:34:15 | return ...; | return |
702-
| ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | return |
702+
| ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | exit |
703703
| ExitMethods.cs:33:9:33:25 | this access | ExitMethods.cs:33:9:33:25 | this access | normal |
704-
| ExitMethods.cs:33:9:33:26 | ...; | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | return |
704+
| ExitMethods.cs:33:9:33:26 | ...; | ExitMethods.cs:33:9:33:25 | call to method ApplicationExit | exit |
705705
| ExitMethods.cs:34:9:34:15 | return ...; | ExitMethods.cs:34:9:34:15 | return ...; | return |
706706
| ExitMethods.cs:38:5:51:5 | {...} | ExitMethods.cs:45:13:45:19 | return ...; | return |
707707
| ExitMethods.cs:38:5:51:5 | {...} | ExitMethods.cs:49:13:49:19 | return ...; | return |
@@ -740,23 +740,25 @@
740740
| ExitMethods.cs:64:13:64:45 | throw ...; | ExitMethods.cs:64:13:64:45 | throw ...; | throw(ArgumentException) |
741741
| ExitMethods.cs:64:19:64:44 | object creation of type ArgumentException | ExitMethods.cs:64:19:64:44 | object creation of type ArgumentException | normal |
742742
| ExitMethods.cs:64:41:64:43 | "b" | ExitMethods.cs:64:41:64:43 | "b" | normal |
743-
| ExitMethods.cs:68:5:70:5 | {...} | ExitMethods.cs:69:9:69:27 | call to method Exit | return |
744-
| ExitMethods.cs:69:9:69:27 | call to method Exit | ExitMethods.cs:69:9:69:27 | call to method Exit | return |
745-
| ExitMethods.cs:69:9:69:28 | ...; | ExitMethods.cs:69:9:69:27 | call to method Exit | return |
743+
| ExitMethods.cs:68:5:70:5 | {...} | ExitMethods.cs:69:9:69:27 | call to method Exit | exit |
744+
| ExitMethods.cs:69:9:69:27 | call to method Exit | ExitMethods.cs:69:9:69:27 | call to method Exit | exit |
745+
| ExitMethods.cs:69:9:69:28 | ...; | ExitMethods.cs:69:9:69:27 | call to method Exit | exit |
746746
| ExitMethods.cs:69:26:69:26 | 0 | ExitMethods.cs:69:26:69:26 | 0 | normal |
747-
| ExitMethods.cs:73:5:83:5 | {...} | ExitMethods.cs:81:13:81:40 | call to method WriteLine | return |
748-
| ExitMethods.cs:74:9:82:9 | try {...} ... | ExitMethods.cs:81:13:81:40 | call to method WriteLine | return |
749-
| ExitMethods.cs:75:9:77:9 | {...} | ExitMethods.cs:76:13:76:18 | call to method Exit | return |
750-
| ExitMethods.cs:76:13:76:18 | call to method Exit | ExitMethods.cs:76:13:76:18 | call to method Exit | return |
747+
| ExitMethods.cs:73:5:83:5 | {...} | ExitMethods.cs:76:13:76:18 | call to method Exit | exit |
748+
| ExitMethods.cs:73:5:83:5 | {...} | ExitMethods.cs:81:13:81:40 | call to method WriteLine | exit |
749+
| ExitMethods.cs:74:9:82:9 | try {...} ... | ExitMethods.cs:76:13:76:18 | call to method Exit | exit |
750+
| ExitMethods.cs:74:9:82:9 | try {...} ... | ExitMethods.cs:81:13:81:40 | call to method WriteLine | exit |
751+
| ExitMethods.cs:75:9:77:9 | {...} | ExitMethods.cs:76:13:76:18 | call to method Exit | exit |
752+
| ExitMethods.cs:76:13:76:18 | call to method Exit | ExitMethods.cs:76:13:76:18 | call to method Exit | exit |
751753
| ExitMethods.cs:76:13:76:18 | this access | ExitMethods.cs:76:13:76:18 | this access | normal |
752-
| ExitMethods.cs:76:13:76:19 | ...; | ExitMethods.cs:76:13:76:18 | call to method Exit | return |
754+
| ExitMethods.cs:76:13:76:19 | ...; | ExitMethods.cs:76:13:76:18 | call to method Exit | exit |
753755
| ExitMethods.cs:79:9:82:9 | {...} | ExitMethods.cs:81:13:81:40 | call to method WriteLine | normal |
754756
| ExitMethods.cs:81:13:81:40 | call to method WriteLine | ExitMethods.cs:81:13:81:40 | call to method WriteLine | normal |
755757
| ExitMethods.cs:81:13:81:41 | ...; | ExitMethods.cs:81:13:81:40 | call to method WriteLine | normal |
756758
| ExitMethods.cs:81:38:81:39 | "" | ExitMethods.cs:81:38:81:39 | "" | normal |
757-
| ExitMethods.cs:86:5:88:5 | {...} | ExitMethods.cs:87:9:87:47 | call to method Exit | return |
758-
| ExitMethods.cs:87:9:87:47 | call to method Exit | ExitMethods.cs:87:9:87:47 | call to method Exit | return |
759-
| ExitMethods.cs:87:9:87:48 | ...; | ExitMethods.cs:87:9:87:47 | call to method Exit | return |
759+
| ExitMethods.cs:86:5:88:5 | {...} | ExitMethods.cs:87:9:87:47 | call to method Exit | exit |
760+
| ExitMethods.cs:87:9:87:47 | call to method Exit | ExitMethods.cs:87:9:87:47 | call to method Exit | exit |
761+
| ExitMethods.cs:87:9:87:48 | ...; | ExitMethods.cs:87:9:87:47 | call to method Exit | exit |
760762
| ExitMethods.cs:91:5:93:5 | {...} | ExitMethods.cs:92:9:92:77 | return ...; | return |
761763
| ExitMethods.cs:91:5:93:5 | {...} | ExitMethods.cs:92:41:92:76 | throw ... | throw(ArgumentException) |
762764
| ExitMethods.cs:92:9:92:77 | return ...; | ExitMethods.cs:92:9:92:77 | return ...; | return |

0 commit comments

Comments
 (0)