1+ // generated by { {generator} }, do not edit
2+ /**
3+ * This module provides generated wrappers around the `CfgNode` type.
4+ *
5+ * INTERNAL: Do not import directly.
6+ */
7+
8+ private import codeql.util.Location
9+ private import codeql.util.Unit
10+ private import { {include_file_import} }
11+
12+ /** Provides the input to `MakeCfgNodes` */
13+ signature module InputSig<LocationSig Loc > {
14+ class CfgNode {
15+ AstNode getAstNode();
16+
17+ string toString();
18+
19+ Loc getLocation();
20+ }
21+
22+ AstNode getDesugared(AstNode n);
23+ }
24+
25+ /**
26+ * Given a `CfgNode` implementation, provides the module `Nodes` that
27+ * contains wrappers around `CfgNode` for relevant classes.
28+ */
29+ module MakeCfgNodes<LocationSig Loc, InputSig <Loc > Input> {
30+ private import Input
31+
32+ final private class AstNodeFinal = AstNode;
33+
34+ final private class CfgNodeFinal = CfgNode;
35+
36+ /**
37+ * INTERNAL: Do not expose.
38+ */
39+ abstract class ParentAstNode extends AstNodeFinal {
40+ /**
41+ * Holds if `child` is a (possibly nested) child of this AST node
42+ * for which we would like to find a matching CFG child.
43+ */
44+ abstract predicate relevantChild(AstNode child);
45+ }
46+
47+ /**
48+ * INTERNAL: Do not expose.
49+ */
50+ abstract class ChildMapping extends Unit {
51+ /**
52+ * Holds if `child` is a (possibly nested) child of AST node `parent`
53+ * for which we would like to find a matching CFG child.
54+ */
55+ final predicate relevantChild(AstNode parent, AstNode child) {
56+ parent.(ParentAstNode).relevantChild(child)
57+ }
58+
59+ /**
60+ * Holds if there is a control flow path from `cfn` to `cfnChild`, where `cfn`
61+ * is a control flow node for this AST node, and `cfnChild` is a control flow
62+ * node for `child`.
63+ *
64+ * This predicate should be implemented at the place where `MakeCfgNodes` is
65+ * invoked. Ideally, `MakeCfgNodes` should be a higher-order parameterized
66+ * module, but since that is currently not supported, we achieve the "callback"
67+ * effect using this `abstract` class instead.
68+ */
69+ cached
70+ abstract predicate hasCfgChild(AstNode parent, AstNode child, CfgNode cfn, CfgNode cfnChild);
71+ }
72+
73+ /** Provides sub classes of `CfgNode`. */
74+ module Nodes {
75+ {{#classes} }
76+ private final class Parent{ {name} } extends ParentAstNode, { {name} } {
77+ override predicate relevantChild(AstNode child) {
78+ none()
79+ {{#properties} }
80+ { {#cfg} }
81+ or
82+ child = this.{ {getter} }({ {#is_indexed} }_{ {/is_indexed} })
83+ { {/cfg} }
84+ { {/properties} }
85+ }
86+ }
87+
88+ /**
89+ { {#doc} }
90+ * { {.} }
91+ { {/doc} }
92+ */
93+ final class { {name} }CfgNode extends CfgNodeFinal{ {#bases} }, { {.} }CfgNode{ {/bases} } {
94+ private {{name} } node;
95+
96+ { {name} }CfgNode() {
97+ node = this.getAstNode()
98+ }
99+
100+ /** Gets the underlying `{ {name} }`. */
101+ { {name} } get{ {name} }() { result = node }
102+
103+ { {#properties} }
104+ /**
105+ * { {> ql_property_doc} } *
106+ { {#description} }
107+ * { {.} }
108+ { {/description} }
109+ { {#internal} }
110+ * INTERNAL: Do not use.
111+ { {/internal} }
112+ */
113+ { {type} }{ {#cfg} }CfgNode{ {/cfg} } { {getter} }({ {#is_indexed} }int index{ {/is_indexed} }) {
114+ {{#cfg} }
115+ any(ChildMapping mapping).hasCfgChild(node, node.{ {getter} }({ {#is_indexed} }index{ {/is_indexed} }), this, result)
116+ { {/cfg} }
117+ { {^cfg} }
118+ { {^is_predicate} }result = { {/is_predicate} }node.{ {getter} }({ {#is_indexed} }index{ {/is_indexed} })
119+ { {/cfg} }
120+ }
121+
122+ { {#is_optional} }
123+ /**
124+ * Holds if `{ {getter} }({ {#is_repeated} }index{ {/is_repeated} })` exists.
125+ { {#internal} }
126+ * INTERNAL: Do not use.
127+ { {/internal} }
128+ */
129+ predicate has{ {singular} }({ {#is_repeated} }int index{ {/is_repeated} }) {
130+ exists(this.{{getter} }({ {#is_repeated} }index{ {/is_repeated} }))
131+ }
132+ { {/is_optional} }
133+ { {#is_indexed} }
134+
135+ /**
136+ * Gets any of the { {doc_plural} }.
137+ { {#internal} }
138+ * INTERNAL: Do not use.
139+ { {/internal} }
140+ */
141+ { {type} }{ {#cfg} }CfgNode{ {/cfg} } { {indefinite_getter} }() {
142+ result = this.{{getter} }(_)
143+ }
144+ { {^is_optional} }
145+
146+ /**
147+ * Gets the number of { {doc_plural} }.
148+ { {#internal} }
149+ * INTERNAL: Do not use.
150+ { {/internal} }
151+ */
152+ int getNumberOf{ {plural} }() {
153+ result = count(int i | exists(this.{{getter} }(i)))
154+ }
155+ { {/is_optional} }
156+ { {/is_indexed} }
157+ { {#is_unordered} }
158+ /**
159+ * Gets the number of { {doc_plural} }.
160+ { {#internal} }
161+ * INTERNAL: Do not use.
162+ { {/internal} }
163+ */
164+ int getNumberOf{ {plural} }() {
165+ result = count(this.{{getter} }())
166+ }
167+ { {/is_unordered} }
168+ { {/properties} }
169+ }
170+ { {/classes} }
171+ }
172+
173+ module Consistency {
174+ private predicate hasCfgNode(AstNode astNode) {
175+ astNode = any(CfgNode cfgNode).getAstNode()
176+ }
177+
178+ query predicate missingCfgChild(CfgNode parent, string pred, int i, AstNode child) {
179+ none()
180+ {{#classes} }
181+ { {#properties} }
182+ { {#cfg} }
183+ or
184+ pred = "{ {getter} }" and
185+ parent = any(Nodes::{ {name} }CfgNode cfgNode, { {name} } astNode |
186+ astNode = cfgNode.get{ {name} }() and
187+ child = getDesugared(astNode.{ {getter} }({ {#is_indexed} }i{ {/is_indexed} }))
188+ { {^is_indexed} }and i = -1{ {/is_indexed} } and
189+ hasCfgNode(child) and
190+ not child = cfgNode.{ {getter} }({ {#is_indexed} }i{ {/is_indexed} }).getAstNode()
191+ |
192+ cfgNode
193+ )
194+ { {/cfg} }
195+ { {/properties} }
196+ { {/classes} }
197+ }
198+ }
199+ }
0 commit comments