@@ -243,3 +243,85 @@ module MakeWithState<StateConfigSig Config> implements DataFlowSig {
243243
244244 import Impl< C >
245245}
246+
247+ signature class PathNodeSig {
248+ /** Gets a textual representation of this element. */
249+ string toString ( ) ;
250+
251+ /**
252+ * Holds if this element is at the specified location.
253+ * The location spans column `startcolumn` of line `startline` to
254+ * column `endcolumn` of line `endline` in file `filepath`.
255+ * For more information, see
256+ * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
257+ */
258+ predicate hasLocationInfo (
259+ string filepath , int startline , int startcolumn , int endline , int endcolumn
260+ ) ;
261+
262+ /** Gets the underlying `Node`. */
263+ Node getNode ( ) ;
264+ }
265+
266+ signature module PathGraphSig< PathNodeSig PathNode> {
267+ /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
268+ predicate edges ( PathNode a , PathNode b ) ;
269+
270+ /** Holds if `n` is a node in the graph of data flow path explanations. */
271+ predicate nodes ( PathNode n , string key , string val ) ;
272+
273+ /**
274+ * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
275+ * a subpath between `par` and `ret` with the connecting edges `arg -> par` and
276+ * `ret -> out` is summarized as the edge `arg -> out`.
277+ */
278+ predicate subpaths ( PathNode arg , PathNode par , PathNode ret , PathNode out ) ;
279+ }
280+
281+ module MergePathGraph<
282+ PathNodeSig PathNode1, PathNodeSig PathNode2, PathGraphSig< PathNode1 > Graph1,
283+ PathGraphSig< PathNode2 > Graph2> {
284+ private newtype TPathNode =
285+ TPathNode1 ( PathNode1 p ) or
286+ TPathNode2 ( PathNode2 p )
287+
288+ class PathNode extends TPathNode {
289+ PathNode1 asPathNode1 ( ) { this = TPathNode1 ( result ) }
290+
291+ PathNode2 asPathNode2 ( ) { this = TPathNode2 ( result ) }
292+
293+ string toString ( ) {
294+ result = this .asPathNode1 ( ) .toString ( ) or
295+ result = this .asPathNode2 ( ) .toString ( )
296+ }
297+
298+ predicate hasLocationInfo (
299+ string filepath , int startline , int startcolumn , int endline , int endcolumn
300+ ) {
301+ this .asPathNode1 ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn ) or
302+ this .asPathNode2 ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn )
303+ }
304+
305+ Node getNode ( ) {
306+ result = this .asPathNode1 ( ) .getNode ( ) or
307+ result = this .asPathNode2 ( ) .getNode ( )
308+ }
309+ }
310+
311+ module PathGraph implements PathGraphSig< PathNode > {
312+ query predicate edges ( PathNode a , PathNode b ) {
313+ Graph1:: edges ( a .asPathNode1 ( ) , b .asPathNode1 ( ) ) or
314+ Graph2:: edges ( a .asPathNode2 ( ) , b .asPathNode2 ( ) )
315+ }
316+
317+ query predicate nodes ( PathNode n , string key , string val ) {
318+ Graph1:: nodes ( n .asPathNode1 ( ) , key , val ) or
319+ Graph2:: nodes ( n .asPathNode2 ( ) , key , val )
320+ }
321+
322+ query predicate subpaths ( PathNode arg , PathNode par , PathNode ret , PathNode out ) {
323+ Graph1:: subpaths ( arg .asPathNode1 ( ) , par .asPathNode1 ( ) , ret .asPathNode1 ( ) , out .asPathNode1 ( ) ) or
324+ Graph2:: subpaths ( arg .asPathNode2 ( ) , par .asPathNode2 ( ) , ret .asPathNode2 ( ) , out .asPathNode2 ( ) )
325+ }
326+ }
327+ }
0 commit comments