@@ -136,6 +136,28 @@ private predicate impossibleDefaultSwitchEdge(Block switchBlock, DefaultCase dc)
136136 val <= switchCaseRangeEnd ( sc ) ) ) )
137137}
138138
139+ /**
140+ * Holds if the function `f` never returns due to not containing a return
141+ * statement (explicit or compiler generated). This can be thought of as
142+ * a lightweight `potentiallyReturningFunction`- reachability of return
143+ * statements is not checked.
144+ */
145+ private predicate nonReturningFunction ( Function f )
146+ {
147+ exists ( f .getBlock ( ) ) and
148+ not exists ( ReturnStmt ret | ret .getEnclosingFunction ( ) = f ) and
149+ not getOptions ( ) .exits ( f )
150+ }
151+
152+ /**
153+ * An edge from a call to a function that never returns is impossible.
154+ */
155+ private predicate impossibleFunctionReturn ( FunctionCall fc , Node succ ) {
156+ nonReturningFunction ( fc .getTarget ( ) ) and
157+ not fc .isVirtual ( ) and
158+ successors_extended ( fc , succ )
159+ }
160+
139161/**
140162 * If `pred` is a function call with (at least) one function target,
141163 * (at least) one such target must be potentially returning.
@@ -158,6 +180,7 @@ cached predicate successors_adapted(Node pred, Node succ) {
158180 and not impossibleTrueEdge ( pred , succ )
159181 and not impossibleSwitchEdge ( pred , succ )
160182 and not impossibleDefaultSwitchEdge ( pred , succ )
183+ and not impossibleFunctionReturn ( pred , succ )
161184 and not getOptions ( ) .exprExits ( pred )
162185}
163186
0 commit comments