Files
codeql/misc/codegen/templates/ql_cfg_nodes.mustache
2024-11-21 10:42:11 +01:00

199 lines
5.3 KiB
Plaintext

// 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<LocationSig Loc> {
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<LocationSig Loc, InputSig<Loc> 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}}
}
}
}