From dc5080c61d73d66d2edbee6d8e52a9366a50695e Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 28 May 2021 10:05:18 +0200 Subject: [PATCH] More variable resolution --- ql/src/codeql_ql/ast/Ast.qll | 105 +++++++++--- ql/src/codeql_ql/ast/internal/AstNodes.qll | 7 +- ql/src/codeql_ql/ast/internal/Variable.qll | 56 +++++-- ql/test/printAst/printAst.expected | 180 ++++++++++----------- 4 files changed, 229 insertions(+), 119 deletions(-) diff --git a/ql/src/codeql_ql/ast/Ast.qll b/ql/src/codeql_ql/ast/Ast.qll index c431396b50a..5c8d4ff2d9c 100644 --- a/ql/src/codeql_ql/ast/Ast.qll +++ b/ql/src/codeql_ql/ast/Ast.qll @@ -2,7 +2,7 @@ import ql private import codeql_ql.ast.internal.AstNodes private import codeql_ql.ast.internal.Module private import codeql_ql.ast.internal.Predicate -private import codeql_ql.ast.internal.Type +import codeql_ql.ast.internal.Type private import codeql_ql.ast.internal.Variable bindingset[name, i] @@ -256,18 +256,28 @@ class CharPred extends TCharPred, Predicate { override AstNode getAChild(string pred_name) { pred_name = "getBody" and result = this.getBody() } } +/** + * A variable definition. This is either a variable declaration or + * an `as` expression. + */ +class VarDef extends TVarDef, AstNode { + /** Gets the name of the declared variable. */ + string getName() { none() } + + override string getAPrimaryQlClass() { result = "VarDef" } + + override string toString() { result = this.getName() } +} + /** * A variable declaration, with a type and a name. */ -class VarDecl extends TVarDecl, AstNode { +class VarDecl extends TVarDecl, VarDef { Generated::VarDecl var; VarDecl() { this = TVarDecl(var) } - /** - * Gets the name for this variable declaration. - */ - string getName() { result = var.getChild(1).(Generated::VarName).getChild().getValue() } + override string getName() { result = var.getChild(1).(Generated::VarName).getChild().getValue() } override string getAPrimaryQlClass() { result = "VarDecl" } @@ -407,6 +417,8 @@ class ModuleMember extends TModuleMember, AstNode { class Declaration extends TDeclaration, AstNode { /** Gets the name of this declaration. */ string getName() { none() } + + final override string toString() { result = this.getName() } } /** An entity that can be declared in a module. */ @@ -1088,19 +1100,21 @@ class ExprAggregate extends TExprAggregate, Expr { /** An aggregate expression, such as `count` or `sum`. */ class Aggregate extends TAggregate, Expr { Generated::Aggregate agg; - Generated::FullAggregateBody body; string kind; Aggregate() { this = TAggregate(agg) and - kind = agg.getChild(0).(Generated::AggId).getValue() and - body = agg.getChild(_) + kind = agg.getChild(0).(Generated::AggId).getValue() } + private Generated::FullAggregateBody getBody1() { result = agg.getChild(_) } + + private Generated::ExprAggregateBody getBody2() { result = agg.getChild(_) } + string getKind() { result = kind } /** Gets the ith declared argument of this quantifier. */ - VarDecl getArgument(int i) { toGenerated(result) = body.getChild(i) } + VarDecl getArgument(int i) { toGenerated(result) = this.getBody1().getChild(i) } /** Gets an argument of this quantifier. */ VarDecl getAnArgument() { result = this.getArgument(_) } @@ -1108,23 +1122,33 @@ class Aggregate extends TAggregate, Expr { /** * Gets the formula restricting the range of this quantifier, if any. */ - Formula getRange() { toGenerated(result) = body.getGuard() } + Formula getRange() { toGenerated(result) = this.getBody1().getGuard() } /** * Gets the ith "as" expression of this aggregate, if any. */ - AsExpr getAsExpr(int i) { toGenerated(result) = body.getAsExprs().getChild(i) } + AsExpr getAsExpr(int i) { + toGenerated(result) = [this.getBody1().getAsExprs(), this.getBody2().getAsExprs()].getChild(i) + } /** * Gets the ith "order by" expression of this aggregate, if any. */ - Expr getOrderBy(int i) { toGenerated(result) = body.getOrderBys().getChild(i).getChild(0) } + Expr getOrderBy(int i) { + toGenerated(result) = + [this.getBody1().getOrderBys(), this.getBody2().getOrderBys()].getChild(i).getChild(0) + } /** * Gets the direction (ascending or descending) of the ith "order by" expression of this aggregate. */ string getOrderbyDirection(int i) { - result = body.getOrderBys().getChild(i).getChild(1).(Generated::Direction).getValue() + result = + [this.getBody1().getOrderBys(), this.getBody2().getOrderBys()] + .getChild(i) + .getChild(1) + .(Generated::Direction) + .getValue() } override string getAPrimaryQlClass() { result = "Aggregate[" + kind + "]" } @@ -1159,13 +1183,15 @@ class Rank extends Aggregate { /** * An "as" expression, such as `foo as bar`. */ -class AsExpr extends TAsExpr, AstNode { +class AsExpr extends TAsExpr, VarDef { Generated::AsExpr asExpr; AsExpr() { this = TAsExpr(asExpr) } override string getAPrimaryQlClass() { result = "AsExpr" } + final override string getName() { result = this.getAsName() } + /** * Gets the name the inner expression gets "saved" under, if it exists. * For example this is `bar` in the expression `foo as bar`. @@ -1189,6 +1215,13 @@ class AsExpr extends TAsExpr, AstNode { } override AstNode getAChild(string pred) { pred = "getInnerExpr" and result = this.getInnerExpr() } + + override string toString() { + result = this.getName() + or + not exists(this.getName()) and + result = "AsExpr" + } } class Identifier extends TIdentifier, Expr { @@ -1196,23 +1229,59 @@ class Identifier extends TIdentifier, Expr { Identifier() { this = TIdentifier(id) } - string getName() { result = id.getChild().(Generated::VarName).getChild().getValue() } + string getName() { none() } + + final override string toString() { result = this.getName() } override string getAPrimaryQlClass() { result = "Identifier" } } /** An access to a variable. */ class VarAccess extends Identifier { - private VarDecl decl; + private VarDef decl; VarAccess() { resolveVariable(this, decl) } /** Gets the accessed variable. */ - VarDecl getDeclaration() { result = decl } + VarDef getDeclaration() { result = decl } + + override string getName() { result = id.getChild().(Generated::VarName).getChild().getValue() } override string getAPrimaryQlClass() { result = "VarAccess" } } +/** An access to a field. */ +class FieldAccess extends Identifier { + private VarDecl decl; + + FieldAccess() { resolveField(this, decl) } + + /** Gets the accessed field. */ + VarDecl getDeclaration() { result = decl } + + override string getName() { result = id.getChild().(Generated::VarName).getChild().getValue() } + + override string getAPrimaryQlClass() { result = "FieldAccess" } +} + +/** An access to `this`. */ +class ThisAccess extends Identifier { + ThisAccess() { any(Generated::This t).getParent() = id } + + override string getName() { result = "this" } + + override string getAPrimaryQlClass() { result = "ThisAccess" } +} + +/** An access to `result`. */ +class ResultAccess extends Identifier { + ResultAccess() { any(Generated::Result r).getParent() = id } + + override string getName() { result = "result" } + + override string getAPrimaryQlClass() { result = "ResultAccess" } +} + /** A `not` formula. */ class Negation extends TNegation, Formula { Generated::Negation neg; diff --git a/ql/src/codeql_ql/ast/internal/AstNodes.qll b/ql/src/codeql_ql/ast/internal/AstNodes.qll index b67747fe8d6..d5fab2c5b58 100644 --- a/ql/src/codeql_ql/ast/internal/AstNodes.qll +++ b/ql/src/codeql_ql/ast/internal/AstNodes.qll @@ -22,7 +22,10 @@ newtype TAstNode = TComparisonFormula(Generated::CompTerm comp) or TComparisonOp(Generated::Compop op) or TQuantifier(Generated::Quantified quant) or - TAggregate(Generated::Aggregate agg) { agg.getChild(_) instanceof Generated::FullAggregateBody } or + TAggregate(Generated::Aggregate agg) { + agg.getChild(_) instanceof Generated::FullAggregateBody or + agg.getChild(_) instanceof Generated::ExprAggregateBody + } or TExprAggregate(Generated::Aggregate agg) { agg.getChild(_) instanceof Generated::ExprAggregateBody } or @@ -161,3 +164,5 @@ class TDeclaration = TTypeDeclaration or TModuleDeclaration; class TTypeDeclaration = TClass or TNewType or TNewTypeBranch; class TModuleDeclaration = TClasslessPredicate or TModule or TClass or TNewType; + +class TVarDef = TVarDecl or TAsExpr; diff --git a/ql/src/codeql_ql/ast/internal/Variable.qll b/ql/src/codeql_ql/ast/internal/Variable.qll index ec471585217..7e5d151be7b 100644 --- a/ql/src/codeql_ql/ast/internal/Variable.qll +++ b/ql/src/codeql_ql/ast/internal/Variable.qll @@ -10,14 +10,33 @@ class VariableScope extends TScope, AstNode { VariableScope getOuterScope() { result = scopeOf(this) } /** Gets a variable declared directly in this scope. */ - VarDecl getADeclaration() { result.getParent() = this } + VarDef getADefinition() { result.getParent() = this } - /** Holds if this scope contains declaration `decl`, either directly or inherited. */ - predicate contains(VarDecl decl) { - decl = this.getADeclaration() + /** Holds if this scope contains variable `decl`, either directly or inherited. */ + predicate containsVar(VarDef decl) { + not this instanceof Class and + decl = this.getADefinition() or - this.getOuterScope().contains(decl) and - not this.getADeclaration().getName() = decl.getName() + decl = this.(Select).getAsExpr(_) + or + decl = this.(Aggregate).getAsExpr(_) + or + this.getOuterScope().containsVar(decl) and + not this.getADefinition().getName() = decl.getName() + } + + /** Holds if this scope contains field `decl`, either directly or inherited. */ + predicate containsField(VarDef decl) { + decl = this.(Class).getAField() + or + this.getOuterScope().containsField(decl) and + not this.getADefinition().getName() = decl.getName() + or + exists(VariableScope sup | + sup = this.(Class).getASuperType().getResolvedType().(ClassType).getDeclaration() and + sup.containsField(decl) and + not this.(Class).getAField().getName() = decl.getName() + ) } } @@ -28,14 +47,31 @@ private AstNode parent(AstNode child) { VariableScope scopeOf(AstNode n) { result = parent*(n.getParent()) } -predicate resolveVariable(Identifier i, VarDecl decl) { - scopeOf(i).contains(decl) and - decl.getName() = i.getName() +private string getName(Identifier i) { + exists(Generated::Variable v | + i = TIdentifier(v) and + result = v.getChild().(Generated::VarName).getChild().getValue() + ) +} + +predicate resolveVariable(Identifier i, VarDef decl) { + scopeOf(i).containsVar(decl) and + decl.getName() = getName(i) +} + +predicate resolveField(Identifier i, VarDef decl) { + scopeOf(i).containsField(decl) and + decl.getName() = getName(i) } module VarConsistency { - query predicate multipleVarDecls(VarAccess v, VarDecl decl) { + query predicate multipleVarDefs(VarAccess v, VarDef decl) { decl = v.getDeclaration() and strictcount(v.getDeclaration()) > 1 } + + query predicate multipleFieldDefs(FieldAccess f, VarDef decl) { + decl = f.getDeclaration() and + strictcount(f.getDeclaration()) > 1 + } } diff --git a/ql/test/printAst/printAst.expected b/ql/test/printAst/printAst.expected index d8ccba97449..c5530702574 100644 --- a/ql/test/printAst/printAst.expected +++ b/ql/test/printAst/printAst.expected @@ -3,8 +3,8 @@ nodes | Foo.qll:1:1:1:17 | Import | semmle.order | 1 | | Foo.qll:1:1:25:2 | TopLevel | semmle.label | [TopLevel] TopLevel | | Foo.qll:1:1:25:2 | TopLevel | semmle.order | 1 | -| Foo.qll:3:1:7:1 | Class | semmle.label | [Class] Class | -| Foo.qll:3:1:7:1 | Class | semmle.order | 3 | +| Foo.qll:3:1:7:1 | Foo | semmle.label | [Class] Foo | +| Foo.qll:3:1:7:1 | Foo | semmle.order | 3 | | Foo.qll:3:19:3:22 | TypeExpr | semmle.label | [TypeExpr] TypeExpr | | Foo.qll:3:19:3:22 | TypeExpr | semmle.order | 4 | | Foo.qll:4:3:4:17 | CharPred | semmle.label | [CharPred] CharPred | @@ -21,22 +21,22 @@ nodes | Foo.qll:6:3:6:8 | TypeExpr | semmle.order | 10 | | Foo.qll:6:3:6:38 | ClassPredicate | semmle.label | [ClassPredicate] ClassPredicate | | Foo.qll:6:3:6:38 | ClassPredicate | semmle.order | 10 | -| Foo.qll:6:23:6:28 | Identifier | semmle.label | [Identifier] Identifier | -| Foo.qll:6:23:6:28 | Identifier | semmle.order | 12 | +| Foo.qll:6:23:6:28 | result | semmle.label | [ResultAccess] result | +| Foo.qll:6:23:6:28 | result | semmle.order | 12 | | Foo.qll:6:23:6:36 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula | | Foo.qll:6:23:6:36 | ComparisonFormula | semmle.order | 12 | | Foo.qll:6:30:6:30 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp | | Foo.qll:6:30:6:30 | ComparisonOp | semmle.order | 14 | | Foo.qll:6:32:6:36 | String | semmle.label | [String] String | | Foo.qll:6:32:6:36 | String | semmle.order | 15 | -| Foo.qll:9:7:11:1 | ClasslessPredicate | semmle.label | [ClasslessPredicate] ClasslessPredicate | -| Foo.qll:9:7:11:1 | ClasslessPredicate | semmle.order | 16 | +| Foo.qll:9:7:11:1 | foo | semmle.label | [ClasslessPredicate] foo | +| Foo.qll:9:7:11:1 | foo | semmle.order | 16 | | Foo.qll:9:21:9:23 | TypeExpr | semmle.label | [TypeExpr] TypeExpr | | Foo.qll:9:21:9:23 | TypeExpr | semmle.order | 17 | -| Foo.qll:9:21:9:25 | VarDecl | semmle.label | [VarDecl] VarDecl | -| Foo.qll:9:21:9:25 | VarDecl | semmle.order | 17 | -| Foo.qll:10:3:10:3 | VarAccess | semmle.label | [VarAccess] VarAccess | -| Foo.qll:10:3:10:3 | VarAccess | semmle.order | 19 | +| Foo.qll:9:21:9:25 | f | semmle.label | [VarDecl] f | +| Foo.qll:9:21:9:25 | f | semmle.order | 17 | +| Foo.qll:10:3:10:3 | f | semmle.label | [VarAccess] f | +| Foo.qll:10:3:10:3 | f | semmle.order | 19 | | Foo.qll:10:3:10:85 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula | | Foo.qll:10:3:10:85 | ComparisonFormula | semmle.order | 19 | | Foo.qll:10:5:10:5 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp | @@ -47,10 +47,10 @@ nodes | Foo.qll:10:12:10:12 | Integer | semmle.order | 23 | | Foo.qll:10:15:10:17 | TypeExpr | semmle.label | [TypeExpr] TypeExpr | | Foo.qll:10:15:10:17 | TypeExpr | semmle.order | 24 | -| Foo.qll:10:15:10:23 | VarDecl | semmle.label | [VarDecl] VarDecl | -| Foo.qll:10:15:10:23 | VarDecl | semmle.order | 24 | -| Foo.qll:10:27:10:31 | VarAccess | semmle.label | [VarAccess] VarAccess | -| Foo.qll:10:27:10:31 | VarAccess | semmle.order | 26 | +| Foo.qll:10:15:10:23 | inner | semmle.label | [VarDecl] inner | +| Foo.qll:10:15:10:23 | inner | semmle.order | 24 | +| Foo.qll:10:27:10:31 | inner | semmle.label | [VarAccess] inner | +| Foo.qll:10:27:10:31 | inner | semmle.order | 26 | | Foo.qll:10:27:10:42 | MemberCall | semmle.label | [MemberCall] MemberCall | | Foo.qll:10:27:10:42 | MemberCall | semmle.order | 26 | | Foo.qll:10:27:10:50 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula | @@ -61,18 +61,18 @@ nodes | Foo.qll:10:46:10:50 | String | semmle.order | 30 | | Foo.qll:10:54:10:58 | AsExpr | semmle.label | [AsExpr] AsExpr | | Foo.qll:10:54:10:58 | AsExpr | semmle.order | 31 | -| Foo.qll:10:54:10:58 | VarAccess | semmle.label | [VarAccess] VarAccess | -| Foo.qll:10:54:10:58 | VarAccess | semmle.order | 31 | -| Foo.qll:10:69:10:73 | VarAccess | semmle.label | [VarAccess] VarAccess | -| Foo.qll:10:69:10:73 | VarAccess | semmle.order | 33 | +| Foo.qll:10:54:10:58 | inner | semmle.label | [VarAccess] inner | +| Foo.qll:10:54:10:58 | inner | semmle.order | 31 | +| Foo.qll:10:69:10:73 | inner | semmle.label | [VarAccess] inner | +| Foo.qll:10:69:10:73 | inner | semmle.order | 33 | | Foo.qll:10:69:10:84 | MemberCall | semmle.label | [MemberCall] MemberCall | | Foo.qll:10:69:10:84 | MemberCall | semmle.order | 33 | -| Foo.qll:13:1:25:1 | ClasslessPredicate | semmle.label | [ClasslessPredicate] ClasslessPredicate | -| Foo.qll:13:1:25:1 | ClasslessPredicate | semmle.order | 35 | +| Foo.qll:13:1:25:1 | calls | semmle.label | [ClasslessPredicate] calls | +| Foo.qll:13:1:25:1 | calls | semmle.order | 35 | | Foo.qll:13:17:13:19 | TypeExpr | semmle.label | [TypeExpr] TypeExpr | | Foo.qll:13:17:13:19 | TypeExpr | semmle.order | 36 | -| Foo.qll:13:17:13:21 | VarDecl | semmle.label | [VarDecl] VarDecl | -| Foo.qll:13:17:13:21 | VarDecl | semmle.order | 36 | +| Foo.qll:13:17:13:21 | f | semmle.label | [VarDecl] f | +| Foo.qll:13:17:13:21 | f | semmle.order | 36 | | Foo.qll:14:3:14:10 | PredicateCall | semmle.label | [PredicateCall] PredicateCall | | Foo.qll:14:3:14:10 | PredicateCall | semmle.order | 38 | | Foo.qll:14:3:16:29 | Disjunction | semmle.label | [Disjunction] Disjunction | @@ -85,16 +85,16 @@ nodes | Foo.qll:14:3:22:16 | Disjunction | semmle.order | 38 | | Foo.qll:14:3:24:23 | Disjunction | semmle.label | [Disjunction] Disjunction | | Foo.qll:14:3:24:23 | Disjunction | semmle.order | 38 | -| Foo.qll:14:9:14:9 | VarAccess | semmle.label | [VarAccess] VarAccess | -| Foo.qll:14:9:14:9 | VarAccess | semmle.order | 44 | +| Foo.qll:14:9:14:9 | f | semmle.label | [VarAccess] f | +| Foo.qll:14:9:14:9 | f | semmle.order | 44 | | Foo.qll:16:3:16:7 | String | semmle.label | [String] String | | Foo.qll:16:3:16:7 | String | semmle.order | 45 | | Foo.qll:16:3:16:29 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula | | Foo.qll:16:3:16:29 | ComparisonFormula | semmle.order | 45 | | Foo.qll:16:9:16:9 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp | | Foo.qll:16:9:16:9 | ComparisonOp | semmle.order | 47 | -| Foo.qll:16:11:16:11 | VarAccess | semmle.label | [VarAccess] VarAccess | -| Foo.qll:16:11:16:11 | VarAccess | semmle.order | 48 | +| Foo.qll:16:11:16:11 | f | semmle.label | [VarAccess] f | +| Foo.qll:16:11:16:11 | f | semmle.order | 48 | | Foo.qll:16:11:16:29 | MemberCall | semmle.label | [MemberCall] MemberCall | | Foo.qll:16:11:16:29 | MemberCall | semmle.order | 48 | | Foo.qll:16:22:16:22 | Integer | semmle.label | [Integer] Integer | @@ -103,8 +103,8 @@ nodes | Foo.qll:16:25:16:25 | Integer | semmle.order | 51 | | Foo.qll:16:28:16:28 | Integer | semmle.label | [Integer] Integer | | Foo.qll:16:28:16:28 | Integer | semmle.order | 52 | -| Foo.qll:18:3:18:3 | VarAccess | semmle.label | [VarAccess] VarAccess | -| Foo.qll:18:3:18:3 | VarAccess | semmle.order | 53 | +| Foo.qll:18:3:18:3 | f | semmle.label | [VarAccess] f | +| Foo.qll:18:3:18:3 | f | semmle.order | 53 | | Foo.qll:18:3:18:9 | InlineCast | semmle.label | [InlineCast] InlineCast | | Foo.qll:18:3:18:9 | InlineCast | semmle.order | 53 | | Foo.qll:18:3:18:20 | MemberCall | semmle.label | [MemberCall] MemberCall | @@ -117,8 +117,8 @@ nodes | Foo.qll:18:22:18:22 | ComparisonOp | semmle.order | 58 | | Foo.qll:18:24:18:28 | String | semmle.label | [String] String | | Foo.qll:18:24:18:28 | String | semmle.order | 59 | -| Foo.qll:20:3:20:3 | VarAccess | semmle.label | [VarAccess] VarAccess | -| Foo.qll:20:3:20:3 | VarAccess | semmle.order | 60 | +| Foo.qll:20:3:20:3 | f | semmle.label | [VarAccess] f | +| Foo.qll:20:3:20:3 | f | semmle.order | 60 | | Foo.qll:20:3:20:9 | InlineCast | semmle.label | [InlineCast] InlineCast | | Foo.qll:20:3:20:9 | InlineCast | semmle.order | 60 | | Foo.qll:20:3:20:13 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula | @@ -127,10 +127,10 @@ nodes | Foo.qll:20:6:20:8 | TypeExpr | semmle.order | 63 | | Foo.qll:20:11:20:11 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp | | Foo.qll:20:11:20:11 | ComparisonOp | semmle.order | 64 | -| Foo.qll:20:13:20:13 | VarAccess | semmle.label | [VarAccess] VarAccess | -| Foo.qll:20:13:20:13 | VarAccess | semmle.order | 65 | -| Foo.qll:22:3:22:3 | VarAccess | semmle.label | [VarAccess] VarAccess | -| Foo.qll:22:3:22:3 | VarAccess | semmle.order | 66 | +| Foo.qll:20:13:20:13 | f | semmle.label | [VarAccess] f | +| Foo.qll:20:13:20:13 | f | semmle.order | 65 | +| Foo.qll:22:3:22:3 | f | semmle.label | [VarAccess] f | +| Foo.qll:22:3:22:3 | f | semmle.order | 66 | | Foo.qll:22:3:22:16 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula | | Foo.qll:22:3:22:16 | ComparisonFormula | semmle.order | 66 | | Foo.qll:22:5:22:5 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp | @@ -139,8 +139,8 @@ nodes | Foo.qll:22:7:22:16 | Aggregate[any] | semmle.order | 69 | | Foo.qll:22:11:22:13 | TypeExpr | semmle.label | [TypeExpr] TypeExpr | | Foo.qll:22:11:22:13 | TypeExpr | semmle.order | 70 | -| Foo.qll:22:11:22:15 | VarDecl | semmle.label | [VarDecl] VarDecl | -| Foo.qll:22:11:22:15 | VarDecl | semmle.order | 70 | +| Foo.qll:22:11:22:15 | f | semmle.label | [VarDecl] f | +| Foo.qll:22:11:22:15 | f | semmle.order | 70 | | Foo.qll:24:3:24:3 | Integer | semmle.label | [Integer] Integer | | Foo.qll:24:3:24:3 | Integer | semmle.order | 72 | | Foo.qll:24:3:24:23 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula | @@ -168,18 +168,18 @@ nodes edges | Foo.qll:1:1:25:2 | TopLevel | Foo.qll:1:1:1:17 | Import | semmle.label | 1 | | Foo.qll:1:1:25:2 | TopLevel | Foo.qll:1:1:1:17 | Import | semmle.order | 1 | -| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:3:1:7:1 | Class | semmle.label | 2 | -| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:3:1:7:1 | Class | semmle.order | 3 | -| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:9:7:11:1 | ClasslessPredicate | semmle.label | 3 | -| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:9:7:11:1 | ClasslessPredicate | semmle.order | 16 | -| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:13:1:25:1 | ClasslessPredicate | semmle.label | 4 | -| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:13:1:25:1 | ClasslessPredicate | semmle.order | 35 | -| Foo.qll:3:1:7:1 | Class | Foo.qll:3:19:3:22 | TypeExpr | semmle.label | 1 | -| Foo.qll:3:1:7:1 | Class | Foo.qll:3:19:3:22 | TypeExpr | semmle.order | 4 | -| Foo.qll:3:1:7:1 | Class | Foo.qll:4:3:4:17 | CharPred | semmle.label | 2 | -| Foo.qll:3:1:7:1 | Class | Foo.qll:4:3:4:17 | CharPred | semmle.order | 5 | -| Foo.qll:3:1:7:1 | Class | Foo.qll:6:3:6:38 | ClassPredicate | semmle.label | 3 | -| Foo.qll:3:1:7:1 | Class | Foo.qll:6:3:6:38 | ClassPredicate | semmle.order | 10 | +| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:3:1:7:1 | Foo | semmle.label | 2 | +| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:3:1:7:1 | Foo | semmle.order | 3 | +| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:9:7:11:1 | foo | semmle.label | 3 | +| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:9:7:11:1 | foo | semmle.order | 16 | +| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:13:1:25:1 | calls | semmle.label | 4 | +| Foo.qll:1:1:25:2 | TopLevel | Foo.qll:13:1:25:1 | calls | semmle.order | 35 | +| Foo.qll:3:1:7:1 | Foo | Foo.qll:3:19:3:22 | TypeExpr | semmle.label | 1 | +| Foo.qll:3:1:7:1 | Foo | Foo.qll:3:19:3:22 | TypeExpr | semmle.order | 4 | +| Foo.qll:3:1:7:1 | Foo | Foo.qll:4:3:4:17 | CharPred | semmle.label | 2 | +| Foo.qll:3:1:7:1 | Foo | Foo.qll:4:3:4:17 | CharPred | semmle.order | 5 | +| Foo.qll:3:1:7:1 | Foo | Foo.qll:6:3:6:38 | ClassPredicate | semmle.label | 3 | +| Foo.qll:3:1:7:1 | Foo | Foo.qll:6:3:6:38 | ClassPredicate | semmle.order | 10 | | Foo.qll:4:3:4:17 | CharPred | Foo.qll:4:11:4:15 | ComparisonFormula | semmle.label | 1 | | Foo.qll:4:3:4:17 | CharPred | Foo.qll:4:11:4:15 | ComparisonFormula | semmle.order | 6 | | Foo.qll:4:11:4:15 | ComparisonFormula | Foo.qll:4:11:4:11 | Integer | semmle.label | 1 | @@ -192,56 +192,56 @@ edges | Foo.qll:6:3:6:38 | ClassPredicate | Foo.qll:6:3:6:8 | TypeExpr | semmle.order | 10 | | Foo.qll:6:3:6:38 | ClassPredicate | Foo.qll:6:23:6:36 | ComparisonFormula | semmle.label | 2 | | Foo.qll:6:3:6:38 | ClassPredicate | Foo.qll:6:23:6:36 | ComparisonFormula | semmle.order | 12 | -| Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:23:6:28 | Identifier | semmle.label | 1 | -| Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:23:6:28 | Identifier | semmle.order | 12 | +| Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:23:6:28 | result | semmle.label | 1 | +| Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:23:6:28 | result | semmle.order | 12 | | Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:30:6:30 | ComparisonOp | semmle.label | 2 | | Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:30:6:30 | ComparisonOp | semmle.order | 14 | | Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:32:6:36 | String | semmle.label | 3 | | Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:32:6:36 | String | semmle.order | 15 | -| Foo.qll:9:7:11:1 | ClasslessPredicate | Foo.qll:9:21:9:25 | VarDecl | semmle.label | 1 | -| Foo.qll:9:7:11:1 | ClasslessPredicate | Foo.qll:9:21:9:25 | VarDecl | semmle.order | 17 | -| Foo.qll:9:7:11:1 | ClasslessPredicate | Foo.qll:10:3:10:85 | ComparisonFormula | semmle.label | 2 | -| Foo.qll:9:7:11:1 | ClasslessPredicate | Foo.qll:10:3:10:85 | ComparisonFormula | semmle.order | 19 | -| Foo.qll:9:21:9:25 | VarDecl | Foo.qll:9:21:9:23 | TypeExpr | semmle.label | 1 | -| Foo.qll:9:21:9:25 | VarDecl | Foo.qll:9:21:9:23 | TypeExpr | semmle.order | 17 | -| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:3:10:3 | VarAccess | semmle.label | 1 | -| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:3:10:3 | VarAccess | semmle.order | 19 | +| Foo.qll:9:7:11:1 | foo | Foo.qll:9:21:9:25 | f | semmle.label | 1 | +| Foo.qll:9:7:11:1 | foo | Foo.qll:9:21:9:25 | f | semmle.order | 17 | +| Foo.qll:9:7:11:1 | foo | Foo.qll:10:3:10:85 | ComparisonFormula | semmle.label | 2 | +| Foo.qll:9:7:11:1 | foo | Foo.qll:10:3:10:85 | ComparisonFormula | semmle.order | 19 | +| Foo.qll:9:21:9:25 | f | Foo.qll:9:21:9:23 | TypeExpr | semmle.label | 1 | +| Foo.qll:9:21:9:25 | f | Foo.qll:9:21:9:23 | TypeExpr | semmle.order | 17 | +| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:3:10:3 | f | semmle.label | 1 | +| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:3:10:3 | f | semmle.order | 19 | | Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:5:10:5 | ComparisonOp | semmle.label | 2 | | Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:5:10:5 | ComparisonOp | semmle.order | 21 | | Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:7:10:85 | Rank | semmle.label | 3 | | Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:7:10:85 | Rank | semmle.order | 22 | | Foo.qll:10:7:10:85 | Rank | Foo.qll:10:12:10:12 | Integer | semmle.label | 1 | | Foo.qll:10:7:10:85 | Rank | Foo.qll:10:12:10:12 | Integer | semmle.order | 23 | -| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:15:10:23 | VarDecl | semmle.label | 2 | -| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:15:10:23 | VarDecl | semmle.order | 24 | +| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:15:10:23 | inner | semmle.label | 2 | +| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:15:10:23 | inner | semmle.order | 24 | | Foo.qll:10:7:10:85 | Rank | Foo.qll:10:27:10:50 | ComparisonFormula | semmle.label | 3 | | Foo.qll:10:7:10:85 | Rank | Foo.qll:10:27:10:50 | ComparisonFormula | semmle.order | 26 | | Foo.qll:10:7:10:85 | Rank | Foo.qll:10:54:10:58 | AsExpr | semmle.label | 4 | | Foo.qll:10:7:10:85 | Rank | Foo.qll:10:54:10:58 | AsExpr | semmle.order | 31 | | Foo.qll:10:7:10:85 | Rank | Foo.qll:10:69:10:84 | MemberCall | semmle.label | 5 | | Foo.qll:10:7:10:85 | Rank | Foo.qll:10:69:10:84 | MemberCall | semmle.order | 33 | -| Foo.qll:10:15:10:23 | VarDecl | Foo.qll:10:15:10:17 | TypeExpr | semmle.label | 1 | -| Foo.qll:10:15:10:23 | VarDecl | Foo.qll:10:15:10:17 | TypeExpr | semmle.order | 24 | -| Foo.qll:10:27:10:42 | MemberCall | Foo.qll:10:27:10:31 | VarAccess | semmle.label | 1 | -| Foo.qll:10:27:10:42 | MemberCall | Foo.qll:10:27:10:31 | VarAccess | semmle.order | 26 | +| Foo.qll:10:15:10:23 | inner | Foo.qll:10:15:10:17 | TypeExpr | semmle.label | 1 | +| Foo.qll:10:15:10:23 | inner | Foo.qll:10:15:10:17 | TypeExpr | semmle.order | 24 | +| Foo.qll:10:27:10:42 | MemberCall | Foo.qll:10:27:10:31 | inner | semmle.label | 1 | +| Foo.qll:10:27:10:42 | MemberCall | Foo.qll:10:27:10:31 | inner | semmle.order | 26 | | Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:27:10:42 | MemberCall | semmle.label | 1 | | Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:27:10:42 | MemberCall | semmle.order | 26 | | Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:44:10:44 | ComparisonOp | semmle.label | 2 | | Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:44:10:44 | ComparisonOp | semmle.order | 29 | | Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:46:10:50 | String | semmle.label | 3 | | Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:46:10:50 | String | semmle.order | 30 | -| Foo.qll:10:54:10:58 | AsExpr | Foo.qll:10:54:10:58 | VarAccess | semmle.label | 1 | -| Foo.qll:10:54:10:58 | AsExpr | Foo.qll:10:54:10:58 | VarAccess | semmle.order | 31 | -| Foo.qll:10:69:10:84 | MemberCall | Foo.qll:10:69:10:73 | VarAccess | semmle.label | 1 | -| Foo.qll:10:69:10:84 | MemberCall | Foo.qll:10:69:10:73 | VarAccess | semmle.order | 33 | -| Foo.qll:13:1:25:1 | ClasslessPredicate | Foo.qll:13:17:13:21 | VarDecl | semmle.label | 1 | -| Foo.qll:13:1:25:1 | ClasslessPredicate | Foo.qll:13:17:13:21 | VarDecl | semmle.order | 36 | -| Foo.qll:13:1:25:1 | ClasslessPredicate | Foo.qll:14:3:24:23 | Disjunction | semmle.label | 2 | -| Foo.qll:13:1:25:1 | ClasslessPredicate | Foo.qll:14:3:24:23 | Disjunction | semmle.order | 38 | -| Foo.qll:13:17:13:21 | VarDecl | Foo.qll:13:17:13:19 | TypeExpr | semmle.label | 1 | -| Foo.qll:13:17:13:21 | VarDecl | Foo.qll:13:17:13:19 | TypeExpr | semmle.order | 36 | -| Foo.qll:14:3:14:10 | PredicateCall | Foo.qll:14:9:14:9 | VarAccess | semmle.label | 1 | -| Foo.qll:14:3:14:10 | PredicateCall | Foo.qll:14:9:14:9 | VarAccess | semmle.order | 44 | +| Foo.qll:10:54:10:58 | AsExpr | Foo.qll:10:54:10:58 | inner | semmle.label | 1 | +| Foo.qll:10:54:10:58 | AsExpr | Foo.qll:10:54:10:58 | inner | semmle.order | 31 | +| Foo.qll:10:69:10:84 | MemberCall | Foo.qll:10:69:10:73 | inner | semmle.label | 1 | +| Foo.qll:10:69:10:84 | MemberCall | Foo.qll:10:69:10:73 | inner | semmle.order | 33 | +| Foo.qll:13:1:25:1 | calls | Foo.qll:13:17:13:21 | f | semmle.label | 1 | +| Foo.qll:13:1:25:1 | calls | Foo.qll:13:17:13:21 | f | semmle.order | 36 | +| Foo.qll:13:1:25:1 | calls | Foo.qll:14:3:24:23 | Disjunction | semmle.label | 2 | +| Foo.qll:13:1:25:1 | calls | Foo.qll:14:3:24:23 | Disjunction | semmle.order | 38 | +| Foo.qll:13:17:13:21 | f | Foo.qll:13:17:13:19 | TypeExpr | semmle.label | 1 | +| Foo.qll:13:17:13:21 | f | Foo.qll:13:17:13:19 | TypeExpr | semmle.order | 36 | +| Foo.qll:14:3:14:10 | PredicateCall | Foo.qll:14:9:14:9 | f | semmle.label | 1 | +| Foo.qll:14:3:14:10 | PredicateCall | Foo.qll:14:9:14:9 | f | semmle.order | 44 | | Foo.qll:14:3:16:29 | Disjunction | Foo.qll:14:3:14:10 | PredicateCall | semmle.label | 1 | | Foo.qll:14:3:16:29 | Disjunction | Foo.qll:14:3:14:10 | PredicateCall | semmle.order | 38 | | Foo.qll:14:3:16:29 | Disjunction | Foo.qll:16:3:16:29 | ComparisonFormula | semmle.label | 2 | @@ -268,16 +268,16 @@ edges | Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:9:16:9 | ComparisonOp | semmle.order | 47 | | Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:11:16:29 | MemberCall | semmle.label | 3 | | Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:11:16:29 | MemberCall | semmle.order | 48 | -| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:11:16:11 | VarAccess | semmle.label | 1 | -| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:11:16:11 | VarAccess | semmle.order | 48 | +| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:11:16:11 | f | semmle.label | 1 | +| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:11:16:11 | f | semmle.order | 48 | | Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:22:16:22 | Integer | semmle.label | 2 | | Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:22:16:22 | Integer | semmle.order | 50 | | Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:25:16:25 | Integer | semmle.label | 3 | | Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:25:16:25 | Integer | semmle.order | 51 | | Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:28:16:28 | Integer | semmle.label | 4 | | Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:28:16:28 | Integer | semmle.order | 52 | -| Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:3:18:3 | VarAccess | semmle.label | 1 | -| Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:3:18:3 | VarAccess | semmle.order | 53 | +| Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:3:18:3 | f | semmle.label | 1 | +| Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:3:18:3 | f | semmle.order | 53 | | Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:6:18:8 | TypeExpr | semmle.label | 2 | | Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:6:18:8 | TypeExpr | semmle.order | 57 | | Foo.qll:18:3:18:20 | MemberCall | Foo.qll:18:3:18:9 | InlineCast | semmle.label | 1 | @@ -288,26 +288,26 @@ edges | Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:22:18:22 | ComparisonOp | semmle.order | 58 | | Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:24:18:28 | String | semmle.label | 3 | | Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:24:18:28 | String | semmle.order | 59 | -| Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:3:20:3 | VarAccess | semmle.label | 1 | -| Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:3:20:3 | VarAccess | semmle.order | 60 | +| Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:3:20:3 | f | semmle.label | 1 | +| Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:3:20:3 | f | semmle.order | 60 | | Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:6:20:8 | TypeExpr | semmle.label | 2 | | Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:6:20:8 | TypeExpr | semmle.order | 63 | | Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:3:20:9 | InlineCast | semmle.label | 1 | | Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:3:20:9 | InlineCast | semmle.order | 60 | | Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:11:20:11 | ComparisonOp | semmle.label | 2 | | Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:11:20:11 | ComparisonOp | semmle.order | 64 | -| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:13:20:13 | VarAccess | semmle.label | 3 | -| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:13:20:13 | VarAccess | semmle.order | 65 | -| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:3:22:3 | VarAccess | semmle.label | 1 | -| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:3:22:3 | VarAccess | semmle.order | 66 | +| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:13:20:13 | f | semmle.label | 3 | +| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:13:20:13 | f | semmle.order | 65 | +| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:3:22:3 | f | semmle.label | 1 | +| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:3:22:3 | f | semmle.order | 66 | | Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:5:22:5 | ComparisonOp | semmle.label | 2 | | Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:5:22:5 | ComparisonOp | semmle.order | 68 | | Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | Aggregate[any] | semmle.label | 3 | | Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | Aggregate[any] | semmle.order | 69 | -| Foo.qll:22:7:22:16 | Aggregate[any] | Foo.qll:22:11:22:15 | VarDecl | semmle.label | 1 | -| Foo.qll:22:7:22:16 | Aggregate[any] | Foo.qll:22:11:22:15 | VarDecl | semmle.order | 70 | -| Foo.qll:22:11:22:15 | VarDecl | Foo.qll:22:11:22:13 | TypeExpr | semmle.label | 1 | -| Foo.qll:22:11:22:15 | VarDecl | Foo.qll:22:11:22:13 | TypeExpr | semmle.order | 70 | +| Foo.qll:22:7:22:16 | Aggregate[any] | Foo.qll:22:11:22:15 | f | semmle.label | 1 | +| Foo.qll:22:7:22:16 | Aggregate[any] | Foo.qll:22:11:22:15 | f | semmle.order | 70 | +| Foo.qll:22:11:22:15 | f | Foo.qll:22:11:22:13 | TypeExpr | semmle.label | 1 | +| Foo.qll:22:11:22:15 | f | Foo.qll:22:11:22:13 | TypeExpr | semmle.order | 70 | | Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:3:24:3 | Integer | semmle.label | 1 | | Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:3:24:3 | Integer | semmle.order | 72 | | Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:5:24:5 | ComparisonOp | semmle.label | 2 |