@@ -50,7 +50,20 @@ private import SuccessorTypes
5050private import Splitting
5151private import semmle.code.csharp.ExprOrStmtParent
5252
53- abstract private class ControlFlowTree extends ControlFlowElement {
53+ /** An element that defines a new CFG scope. */
54+ class CfgScope extends Element , @top_level_exprorstmt_parent { }
55+
56+ module ControlFlowTree {
57+ private class Range_ = @callable or @control_flow_element;
58+
59+ class Range extends Element , Range_ { }
60+
61+ private predicate id ( Range x , Range y ) { x = y }
62+
63+ predicate idOf ( Range x , int y ) = equivalenceRelation( id / 2 ) ( x , y )
64+ }
65+
66+ abstract private class ControlFlowTree extends ControlFlowTree:: Range {
5467 /**
5568 * Holds if `first` is the first element executed within this control
5669 * flow element.
@@ -103,26 +116,10 @@ predicate last(ControlFlowTree cft, ControlFlowElement last, Completion c) {
103116pragma [ nomagic]
104117predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
105118 any ( ControlFlowTree cft ) .succ ( pred , succ , c )
106- or
107- exists ( Constructor con , InitializerSplitting:: InitializedInstanceMember m , int i |
108- last ( m .getInitializer ( ) , pred , c ) and
109- c instanceof NormalCompletion and
110- InitializerSplitting:: constructorInitializeOrder ( con , m , i )
111- |
112- // Flow from one member initializer to the next
113- exists ( InitializerSplitting:: InitializedInstanceMember next |
114- InitializerSplitting:: constructorInitializeOrder ( con , next , i + 1 ) and
115- first ( next .getInitializer ( ) , succ )
116- )
117- or
118- // Flow from last member initializer to constructor body
119- m = InitializerSplitting:: lastConstructorInitializer ( con ) and
120- first ( con .getBody ( ) , succ )
121- )
122119}
123120
124121/** Holds if `first` is first executed when entering `scope`. */
125- predicate succEntry ( @top_level_exprorstmt_parent scope , ControlFlowElement first ) {
122+ predicate scopeFirst ( CfgScope scope , ControlFlowElement first ) {
126123 scope =
127124 any ( Callable c |
128125 if exists ( c .( Constructor ) .getInitializer ( ) )
@@ -142,7 +139,7 @@ predicate succEntry(@top_level_exprorstmt_parent scope, ControlFlowElement first
142139}
143140
144141/** Holds if `scope` is exited when `last` finishes with completion `c`. */
145- predicate succExit ( ControlFlowElement last , Callable scope , Completion c ) {
142+ predicate scopeLast ( Callable scope , ControlFlowElement last , Completion c ) {
146143 last ( scope .getBody ( ) , last , c ) and
147144 not c instanceof GotoCompletion
148145 or
@@ -153,6 +150,33 @@ predicate succExit(ControlFlowElement last, Callable scope, Completion c) {
153150 )
154151}
155152
153+ private class CallableTree extends ControlFlowTree , Callable {
154+ final override predicate propagatesAbnormal ( ControlFlowElement child ) { none ( ) }
155+
156+ final override predicate first ( ControlFlowElement first ) { none ( ) }
157+
158+ final override predicate last ( ControlFlowElement last , Completion c ) { none ( ) }
159+
160+ final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
161+ exists ( Constructor con , InitializerSplitting:: InitializedInstanceMember m , int i |
162+ this = con and
163+ last ( m .getInitializer ( ) , pred , c ) and
164+ c instanceof NormalCompletion and
165+ InitializerSplitting:: constructorInitializeOrder ( con , m , i )
166+ |
167+ // Flow from one member initializer to the next
168+ exists ( InitializerSplitting:: InitializedInstanceMember next |
169+ InitializerSplitting:: constructorInitializeOrder ( con , next , i + 1 ) and
170+ first ( next .getInitializer ( ) , succ )
171+ )
172+ or
173+ // Flow from last member initializer to constructor body
174+ m = InitializerSplitting:: lastConstructorInitializer ( con ) and
175+ first ( con .getBody ( ) , succ )
176+ )
177+ }
178+ }
179+
156180/**
157181 * A control flow element where the children are evaluated following a
158182 * standard left-to-right evaluation. The actual evaluation order is
@@ -347,7 +371,7 @@ module Expressions {
347371 not this instanceof ConstructorInitializer
348372 }
349373
350- final override ControlFlowTree getChildElement ( int i ) { result = getExprChild ( this , i ) }
374+ final override ControlFlowElement getChildElement ( int i ) { result = getExprChild ( this , i ) }
351375
352376 final override predicate first ( ControlFlowElement first ) {
353377 first ( this .getFirstChild ( ) , first )
@@ -945,7 +969,7 @@ module Statements {
945969 )
946970 }
947971
948- final override ControlFlowTree getChildElement ( int i ) {
972+ final override ControlFlowElement getChildElement ( int i ) {
949973 result =
950974 rank [ i + 1 ] ( ControlFlowElement cfe , int j | cfe = this .getChildElement0 ( j ) | cfe order by j )
951975 }
0 commit comments