@@ -239,38 +239,55 @@ module ControlFlow {
239239 /** Holds if this node has more than one successor. */
240240 predicate isBranch ( ) { strictcount ( this .getASuccessor ( ) ) > 1 }
241241
242- /** Gets the enclosing callable of this control flow node. */
242+ /** Gets the enclosing callable of this control flow node, if any . */
243243 Callable getEnclosingCallable ( ) { none ( ) }
244+
245+ /** Gets the enclosing entry element of this control flow node. */
246+ ControlFlowEntryElement getEnclosingElement ( ) { none ( ) }
244247 }
245248
246249 /** Provides different types of control flow nodes. */
247250 module Nodes {
248- /** A node for a callable entry point. */
251+ private import semmle.code.csharp.Enclosing:: Internal
252+
253+ /** An entry node, for example a callable or a field initializer. */
249254 class EntryNode extends Node , TEntryNode {
250- /** Gets the callable that this entry applies to. */
251- Callable getCallable ( ) { this = TEntryNode ( result ) }
255+ private ControlFlowEntryElement e ;
256+
257+ EntryNode ( ) { this = TEntryNode ( e ) }
258+
259+ /** Gets the callable that this entry applies to, if any. */
260+ Callable getCallable ( ) { result = e }
252261
253262 override BasicBlocks:: EntryBlock getBasicBlock ( ) { result = Node .super .getBasicBlock ( ) }
254263
255264 override Callable getEnclosingCallable ( ) { result = this .getCallable ( ) }
256265
257- override Location getLocation ( ) { result = getCallable ( ) . getLocation ( ) }
266+ override ControlFlowEntryElement getEnclosingElement ( ) { result = e }
258267
259- override string toString ( ) { result = "enter " + getCallable ( ) .toString ( ) }
268+ override Location getLocation ( ) { result = this .getEnclosingElement ( ) .getLocation ( ) }
269+
270+ override string toString ( ) { result = "enter " + this .getEnclosingElement ( ) .toString ( ) }
260271 }
261272
262- /** A node for a callable exit point . */
273+ /** An exit node, for example a callable or a field initializer . */
263274 class ExitNode extends Node , TExitNode {
264- /** Gets the callable that this exit applies to. */
265- Callable getCallable ( ) { this = TExitNode ( result ) }
275+ private ControlFlowEntryElement e ;
276+
277+ ExitNode ( ) { this = TExitNode ( e ) }
278+
279+ /** Gets the callable that this exit applies to, if any. */
280+ Callable getCallable ( ) { result = e }
266281
267282 override BasicBlocks:: ExitBlock getBasicBlock ( ) { result = Node .super .getBasicBlock ( ) }
268283
269284 override Callable getEnclosingCallable ( ) { result = this .getCallable ( ) }
270285
271- override Location getLocation ( ) { result = getCallable ( ) . getLocation ( ) }
286+ override ControlFlowEntryElement getEnclosingElement ( ) { result = e }
272287
273- override string toString ( ) { result = "exit " + getCallable ( ) .toString ( ) }
288+ override Location getLocation ( ) { result = this .getEnclosingElement ( ) .getLocation ( ) }
289+
290+ override string toString ( ) { result = "exit " + this .getEnclosingElement ( ) .toString ( ) }
274291 }
275292
276293 /**
@@ -289,6 +306,10 @@ module ControlFlow {
289306
290307 override Callable getEnclosingCallable ( ) { result = cfe .getEnclosingCallable ( ) }
291308
309+ override ControlFlowEntryElement getEnclosingElement ( ) {
310+ exprEnclosingEntryElement ( cfe , result )
311+ }
312+
292313 override ControlFlowElement getElement ( ) { result = cfe }
293314
294315 override string toString ( ) {
@@ -1824,27 +1845,32 @@ module ControlFlow {
18241845 }
18251846
18261847 /**
1827- * Gets the control flow element that is first executed when entering
1828- * callable `c`.
1848+ * Gets the control flow element that is first executed when entering `e`.
18291849 */
1830- ControlFlowElement succEntry ( @top_level_exprorstmt_parent p ) {
1831- p = any ( Callable c |
1850+ ControlFlowElement succEntry ( ControlFlowEntryElement e ) {
1851+ e = any ( Callable c |
18321852 if exists ( c .( Constructor ) .getInitializer ( ) )
18331853 then result = first ( c .( Constructor ) .getInitializer ( ) )
18341854 else result = first ( c .getBody ( ) )
18351855 )
18361856 or
1837- expr_parent_top_level_adjusted ( any ( Expr e | result = first ( e ) ) , _, p ) and
1838- not p instanceof Callable
1857+ expr_parent_top_level_adjusted ( any ( Expr e0 | result = first ( e0 ) ) , _, e ) and
1858+ not e instanceof Callable
18391859 }
18401860
18411861 /**
1842- * Gets the callable that is exited when `cfe` finishes with completion `c`,
1862+ * Gets the element that is exited when `cfe` finishes with completion `c`,
18431863 * if any.
18441864 */
1845- Callable succExit ( ControlFlowElement cfe , Completion c ) {
1846- cfe = last ( result .getBody ( ) , c ) and
1865+ ControlFlowEntryElement succExit ( ControlFlowElement cfe , Completion c ) {
1866+ cfe = last ( result .( Callable ) . getBody ( ) , c ) and
18471867 not c instanceof GotoCompletion
1868+ or
1869+ exists ( Expr e |
1870+ expr_parent_top_level_adjusted ( e , _, result ) and
1871+ cfe = last ( e , c ) and
1872+ not result instanceof Callable
1873+ )
18481874 }
18491875 }
18501876 import Successor
@@ -1859,13 +1885,13 @@ module ControlFlow {
18591885 */
18601886 cached
18611887 newtype TNode =
1862- TEntryNode ( Callable c ) {
1888+ TEntryNode ( ControlFlowEntryElement e ) {
18631889 Stages:: ControlFlowStage:: forceCachingInSameStage ( ) and
1864- succEntrySplits ( c , _, _, _)
1890+ succEntrySplits ( e , _, _, _)
18651891 } or
1866- TExitNode ( Callable c ) {
1892+ TExitNode ( ControlFlowEntryElement e ) {
18671893 exists ( Reachability:: SameSplitsBlock b | b .isReachable ( _) |
1868- succExitSplits ( b .getAnElement ( ) , _, c , _)
1894+ succExitSplits ( b .getAnElement ( ) , _, e , _)
18691895 )
18701896 } or
18711897 TElementNode ( ControlFlowElement cfe , Splits splits ) {
@@ -1875,18 +1901,20 @@ module ControlFlow {
18751901 /** Gets a successor node of a given flow type, if any. */
18761902 cached
18771903 Node getASuccessorByType ( Node pred , SuccessorType t ) {
1878- // Callable entry node -> callable body
1879- exists ( ControlFlowElement succElement , Splits succSplits |
1880- result = TElementNode ( succElement , succSplits )
1881- |
1882- succEntrySplits ( pred . ( Nodes :: EntryNode ) . getCallable ( ) , succElement , succSplits , t )
1904+ // Entry node -> body
1905+ exists ( ControlFlowElement succElement , Splits succSplits , ControlFlowEntryElement e |
1906+ result = TElementNode ( succElement , succSplits ) and
1907+ pred = TEntryNode ( e ) and
1908+ succEntrySplits ( e , succElement , succSplits , t )
18831909 )
18841910 or
18851911 exists ( ControlFlowElement predElement , Splits predSplits |
18861912 pred = TElementNode ( predElement , predSplits )
18871913 |
1888- // Element node -> callable exit
1889- succExitSplits ( predElement , predSplits , result .( Nodes:: ExitNode ) .getCallable ( ) , t )
1914+ // Element node -> exit node
1915+ exists ( ControlFlowEntryElement e | result = TExitNode ( e ) |
1916+ succExitSplits ( predElement , predSplits , e , t )
1917+ )
18901918 or
18911919 // Element node -> element node
18921920 exists ( ControlFlowElement succElement , Splits succSplits , Completion c |
0 commit comments