// generated by {{generator}}, do not edit /** * This module provides generated wrappers around the `CfgNode` type. * * INTERNAL: Do not import directly. */ private import codeql.util.Location private import codeql.util.Unit private import {{include_file_import}} /** Provides the input to `MakeCfgNodes` */ signature module InputSig { class CfgNode { AstNode getAstNode(); string toString(); Loc getLocation(); } AstNode getDesugared(AstNode n); } /** * Given a `CfgNode` implementation, provides the module `Nodes` that * contains wrappers around `CfgNode` for relevant classes. */ module MakeCfgNodes Input> { private import Input final private class AstNodeFinal = AstNode; final private class CfgNodeFinal = CfgNode; /** * INTERNAL: Do not expose. */ abstract class ParentAstNode extends AstNodeFinal { /** * Holds if `child` is a (possibly nested) child of this AST node * for which we would like to find a matching CFG child. */ abstract predicate relevantChild(AstNode child); } /** * INTERNAL: Do not expose. */ abstract class ChildMapping extends Unit { /** * Holds if `child` is a (possibly nested) child of AST node `parent` * for which we would like to find a matching CFG child. */ final predicate relevantChild(AstNode parent, AstNode child) { parent.(ParentAstNode).relevantChild(child) } /** * Holds if there is a control-flow path from `cfn` to `cfnChild`, where `cfn` * is a control-flow node for this AST node, and `cfnChild` is a control-flow * node for `child`. * * This predicate should be implemented at the place where `MakeCfgNodes` is * invoked. Ideally, `MakeCfgNodes` should be a higher-order parameterized * module, but since that is currently not supported, we achieve the "callback" * effect using this `abstract` class instead. */ cached abstract predicate hasCfgChild(AstNode parent, AstNode child, CfgNode cfn, CfgNode cfnChild); } /** Provides sub classes of `CfgNode`. */ module Nodes { {{#classes}} private final class Parent{{name}} extends ParentAstNode, {{name}} { override predicate relevantChild(AstNode child) { none() {{#properties}} {{#cfg}} or child = this.{{getter}}({{#is_indexed}}_{{/is_indexed}}) {{/cfg}} {{/properties}} } } /** {{#doc}} * {{.}} {{/doc}} */ final class {{name}}CfgNode extends CfgNodeFinal{{#bases}}, {{.}}CfgNode{{/bases}} { private {{name}} node; {{name}}CfgNode() { node = this.getAstNode() } /** Gets the underlying `{{name}}`. */ {{name}} get{{name}}() { result = node } {{#properties}} /** * {{>ql_property_doc}} * {{#description}} * {{.}} {{/description}} {{#internal}} * INTERNAL: Do not use. {{/internal}} */ {{type}}{{#cfg}}CfgNode{{/cfg}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) { {{#cfg}} any(ChildMapping mapping).hasCfgChild(node, node.{{getter}}({{#is_indexed}}index{{/is_indexed}}), this, result) {{/cfg}} {{^cfg}} {{^is_predicate}}result = {{/is_predicate}}node.{{getter}}({{#is_indexed}}index{{/is_indexed}}) {{/cfg}} } {{#is_optional}} /** * Holds if `{{getter}}({{#is_repeated}}index{{/is_repeated}})` exists. {{#internal}} * INTERNAL: Do not use. {{/internal}} */ predicate has{{singular}}({{#is_repeated}}int index{{/is_repeated}}) { exists(this.{{getter}}({{#is_repeated}}index{{/is_repeated}})) } {{/is_optional}} {{#is_indexed}} /** * Gets any of the {{doc_plural}}. {{#internal}} * INTERNAL: Do not use. {{/internal}} */ {{type}}{{#cfg}}CfgNode{{/cfg}} {{indefinite_getter}}() { result = this.{{getter}}(_) } {{^is_optional}} /** * Gets the number of {{doc_plural}}. {{#internal}} * INTERNAL: Do not use. {{/internal}} */ int getNumberOf{{plural}}() { result = count(int i | exists(this.{{getter}}(i))) } {{/is_optional}} {{/is_indexed}} {{#is_unordered}} /** * Gets the number of {{doc_plural}}. {{#internal}} * INTERNAL: Do not use. {{/internal}} */ int getNumberOf{{plural}}() { result = count(this.{{getter}}()) } {{/is_unordered}} {{/properties}} } {{/classes}} } module Consistency { private predicate hasCfgNode(AstNode astNode) { astNode = any(CfgNode cfgNode).getAstNode() } query predicate missingCfgChild(CfgNode parent, string pred, int i, AstNode child) { none() {{#classes}} {{#properties}} {{#cfg}} or pred = "{{getter}}" and parent = any(Nodes::{{name}}CfgNode cfgNode, {{name}} astNode | astNode = cfgNode.get{{name}}() and child = getDesugared(astNode.{{getter}}({{#is_indexed}}i{{/is_indexed}})) {{^is_indexed}}and i = -1{{/is_indexed}} and hasCfgNode(child) and not child = cfgNode.{{getter}}({{#is_indexed}}i{{/is_indexed}}).getAstNode() | cfgNode ) {{/cfg}} {{/properties}} {{/classes}} } } }